Lispの話(高階関数・lambda記法)
こんにちは、たくさん寝太郎です。
昨日ハンバーグを作ったらとても上手に出来ました。
高階関数
mapcar
リストの要素全体にある関数を作用させたい時は次のように書きます。
(mapcar #'expt '(1 2 3) '(1 2 3)) ;=>(1 4 27)
mapcarは第一引数に関数を、第二引数以降にリストを受け取ってリストの各要素に関数を作用させる関数です。
mapcarのように他の関数を引数として受け取る関数を高階関数と言います。
例として、与えたリストの各要素を二乗するプログラムを考えてみましょう。
(defun square (x) (* x x)) ;数xを二乗する関数squareを定義 (mapcar #'square '(1 2 3)) ;=>(1 4 9)
#'という記号はfunctionオペレータの略記です。
(mapcar (function square) '(1 2 3)) ;上のコードはこれと同値
apply
applyも第一引数に関数、第二引数にリストを受け取りますが、こちらは第二引数のリストの要素全体を引数として関数を呼び出したような動きをします。
(apply #'+ '(1 2 3)) ;=>6
Common Lispでは関数を値として扱う時にfunctionオペレータを使って引数が関数であることを明示しなければなりません。
例えば、変数carを定義した時にfunctionオペレータが無いとLispはcarが関数carなのか変数carなのか判断できません。
Common Lispでは変数名と関数名を別々に管理しているのでfunctionオペレータが必要ですが、Schemeは同じ名前空間を共有しているのでfunctionオペレータは必要ありません。
Lambda(無名関数)
先ほど数の二乗を計算する関数squareを定めました。
(defun square (x) (* x x))
関数squareそのものを取り出すにはfunctionオペレータを用います。
#'square ;=>#<FUNCTION SQUARE (X) (DECLARE (SYSTEM::IN-DEFUN SQUARE)) (BLOCK SQUARE (* X X))>
lambdaコマンドはこの流れを一度に行います。
(lambda (x) (* x x)) ;=>#<FUNCTION :LAMBDA (X) (* X X)>
Lispはラムダ算法という数学的な概念から直接導かれたプログラミング言語ということもありlambdaコマンドはLispにおいて重要なものとなっています。
関数を値として渡すことを多用するプログラミングスタイルを高階プログラミングといいます。
以上でLand of Lispの第7章の最初まで終わりました。
十月までに第3部(~13章)を読み終えられるよう頑張ろうと思います...。