My開発メモ

applyはリストを展開する (applyの使い方: Common-Lisp)

“apply”という関数の使い方が、イマイチわかりづらかったので、いろいろ調べたことをまとめておく。

(apply fn lst) — lst(リスト) に fn(関数) を適用する。

(1) アトムを引数にとる関数の場合

CL-USER> (apply #'+ '(1 2 3))
6

+ は、任意の数の引数(アトム)をとり、それらの和を返す。

‘(1 2 3) 全体に + が適用された。すなわち (+ 1 2 3) と同じ。
この場合、'(1 2 3) のリストが展開されて、+ が適用されている。

applyを使って次の関数を作る。

(defun sum (lst)
  (apply #'+ lst))

この場合、次のように sum関数を使う。

CL-USER> (sum '(1 2 3))
6

ここで &rest を使って、可変長の引数を渡せるようにすると・・・、

(defun sum (&rest lst)
  (apply #'+ lst))

次のように、リストではなく、個別の数字で引数を任意の数だけ渡せるようになる。

CL-USER> (sum 1 2 3)
6

&rest は、与えられた引数をリストにして、関数本体で処理されるようにする。

(2) リストを引数にする場合

1+ の場合を考えてみる。

1+ は、引数が数(アトム)の場合、その数に1を加算するが、数のリストの場合、
mapcar を使えば、リストの各要素に 1+ を適用できる。

CL-USER> (mapcar #'1+ '(1 2 3))
(2 3 4)

add1 という関数にすると・・・

(defun add1 (lst)
  (mapcar #'1+ lst))
CL-USER> (add1 '(1 2 3))
(2 3 4)

&rest を使うと・・・

(defun add1 (&rest lst)
  (mapcar #'1+ lst))
CL-USER> (add1 1 2 3 4 5))
(2 3 4 5 6)

(3) apply を組合せる

apply はリストを展開して 引数の関数に渡すから、次のようにしなければならない。

(apply #'mapcar #'1+ '((1 2 3))

関数にすると、次のようになる。

(defun add1 (lst)
  (apply #'mapcar #'1+ lst))

この場合、次のようにリストを渡さねばならない。

CL-USER> (add1 '((1 2 3)))
(2 3 4)

applyはリストを展開して mapcar に渡すので、'(1 2 3) の形で mapcar に
渡さなければならないので、'((1 2 3)) でなければならない。

しかし、次のように &rest を使うと、引数を自動でリストにしてくれる。

(defun add1 (&rest lst)
  (apply #'mapcar #'1+ lst))

この場合は、次のようにできる。

CL-USER> (add1 '(1 2 3))
(2 3 4)

カテゴリー: Lisp, memo

タグ: &rest, apply, clisp, common, common-lisp, Lisp, mapcar, rest

カウント: 140