この記事は, Lisp Advent Calendar 2019の11日目の記事です.
この記事のライセンスはCC-BYとします.
この記事は, 10日目の記事の補足になるかもしれない小ネタ記事です.
reduceの使い方の指針について触れます.
使用プログラミング言語は, Common Lispです.
が, JavaScriptのreduce, reduceRightや, Haskellのfoldl, foldrとかも同じだと思うので, もしかしたら参考になるかも.
再掲 10日目の補足 andの展開形
各処理系の実装は参考にしてないけど, 展開系は参考にしました. 1
CL-USER> (macroexpand '(and))
T
T
CL-USER> (macroexpand '(and a))
(THE T A)
T
CL-USER> (macroexpand '(and a b c))
(IF (IF A
B)
C)
T
THEは無視して, Aは, (IF T A)だと思うと,
(IF (IF (IF T A) B) C)
この形を見ると, reduceで処理できることが分かります.
reduceの使い方 より具体的にのその前に
reduceの使い方の指針を示す前に, 以下の関数を定義しておきます.
(defun snoc (list elt)
(append list (list elt)))
これを使うと, リスト(1 2 3)は, 以下の2パターンで書けます.
CL-USER> (snoc (snoc (snoc nil 1) 2) 3)
(1 2 3)
CL-USER> (cons 1 (cons 2 (cons 3 nil)))
(1 2 3)
reduceの使い方
上のパターンの,
CL-USER> (snoc (snoc (snoc nil 1) 2) 3)
(1 2 3)
について, この式のsnocをある関数func, nilをある値zと入れ替えたような形,
(func (func (func z 1) 2) 3)
で書ける場合は,
(reduce #'func '(1 2 3) :initial-value z)
とreduceで書けます.
reduce (from-endオプションがt)
逆に, 下のパターンの,
CL-USER> (cons 1 (cons 2 (cons 3 nil)))
(1 2 3)
について, この式のconsをある関数func, nilをある値zと入れ替えたような形,
(func 1 (func 2 (func 3 z)))
で書ける場合は,
(reduce #'func '(1 2 3) :initial-value z :from-end t)
と:from-endオプションがtのreduceで書けます.
まとめ
reduce難しくないよ.
この記事中の例で使ったリスト(1 2 3)は適当に自分が使いたい場合に読み替えて使ってください.
あと, 数学が好きな人はcatamorphismとか調べてみると幸せになれるかもしれません. 2