見出し画像

関数型プログラミング事始め (10) Lispは関数型(続)

関数型プログラミングがはじめての方へ贈る入門の書
前節:Lispは関数型 次節:Lisp処理系の導入
参考書:
・五味 弘「はじめてのLisp関数型プログラミング」技術評論社(2016)
・大山口 通夫、五味 弘「プログラミング言語論」コロナ社(2008)
・五味 弘「関数型プログラミングと数学(ITと数学)」技術評論社(2021)

Lispは関数型プログラミング言語の元祖です。誰が何と言ってもそうです。たぶん。前回ではLispでの副作用やイミュータブルデータ、再帰プログラミングの話をしました。今回はラムダ式や高階関数、遅延評価、無限リストなどのモナド実装を紹介していきます。

(4) ラムダ計算

コンピュータの計算モデルとして、ラムダ計算 (λ(lambda) calculus)があります。ラムダ計算はα変換(α-conversion、名前変換)とβ簡約(β-reduction、関数適用)、η変換(η-conversion、関数の等価/外延性)の規則からなります。

このラムダ計算は関数型プログラミングの計算モデルであるとともに、すべてのプログラミング言語の関数適用の基礎にもなっています。
なおラムダ計算については後日紹介する予定です。

このラムダ計算を実装するための言語としてLispはマッカーシーによって提唱されました。Lispには(lambda (x) (+ x 1))のようにラムダ計算の表記であるラムダ式(lambda expression)をそのまま使えます。まさにLispはラムダ計算の申し子です。

このラムダ式はJavaなどの他の言語でも採用されています。匿名関数を実装する手段として利用されている場合が多いですが、他の言語でも関数型プログラミングの萌芽が出てきています。まさに関数型プログラミングの有用性は広く認識されています。

(5) 高階関数

高階関数(higher-order function)は関数の引数や値に関数そのものを使う関数です。つまり関数も他の整数や文字列、配列と同じように関数の引数や値として扱うということです。もちろんLispではラムダ式をそのまま関数として、普通のデータのように使えます。これをファーストクラスオブジェクト(first class object、第1級データ)と呼んでいます。

ただし高階関数は読み書きが難しいものです。プログラミングも難しいですがデバッギングも難しいものです。そこで高階関数を手作りするのではなく、高階関数のライブラリ関数を使うのが常套手段になっています。

ライブラリですから使うパターンが決まっていて、作るのに間違いが少なくなります。それにそのプログラムを読むときにも間違いがありません。Lispには高階関数のライブラリ関数としてmapcarやmaplistなどのmap関数、関数適用を簡約するreduce関数があります。これらのライブラリ関数を使って、高階関数を気楽に使えます。

(6) 遅延評価

遅延評価(lazy evaluation)とは内側優先・左側優先で関数を適用する正格評価(strict evaluation)以外の適用順序の評価を言います。つまり通常の正格評価と比較して、1個以上の関数がいつもより遅延して実行されるというものです。

関数型プログラミング言語ではこの遅延評価の機能を持っているのが一般的です。普通のLispでは遅延評価の機能を直接的には持っていません。なおLispは非常に拡張性の高い言語なので遅延評価の機能を最初から持つものもあります。

そこでLispでは関数を引数として渡し、その関数の実行をプログラムで制御することで遅延評価を実装します。これは簡単に実装できますのでLispでは気楽に遅延評価を使っています。

(7) その他

関数型プログラミング言語ではモナドやモノイドなどの機能があります。これらを実装するためには無限リスト(infinite list)などの機能が必要になります。

Lispでは無限リストは最初からは用意されていませんが、これを実装するのは容易です。リストと遅延評価で実装でき、遅延評価はラムダ式で実装できます。無限リストについては後日紹介する予定にしています。

しかしこれらの機能は入出力などの副作用をなくすための、いわば完全な原理主義的な関数型プログラミングです。そうではなく、入出力以外は副作用を生じないようにするが、入出力などは典型的な普通のプログラミングで行う不純だけど、現実的な関数型プログラミングでも、効果は大きいです。

関数型プログラミングは気楽に楽しみながら、でもその効果を味わってもらうのがいいでしょう。このためにはLispは最適です。本当です。たぶん。

(蛇足)なおLispでなくJavaなどの普通の言語でも関数型プログラミングはできます。原始時代に戻れば、関数型プログラミング言語も結局はフォン・ノイマン型コンピュータで実装されているのですから。

(次回予告) 2.2 Lisp事始め

次回はLispの関数紹介の前に、Lispの概観を見ていくことにします。Lispは他の言語とまったく異なりますからカルチャーショックを受けるでしょう。これをお楽しみに。

参考:プログラミング言語はどれがお得?(前編)|五味弘 (note.com)
参考:プログラミング言語はどれがお得?(後編)|五味弘 (note.com)

よろしければサポートをお願いします!