LoginSignup
9
2

More than 3 years have passed since last update.

reduceの使い方

Last updated at Posted at 2019-12-10

この記事は, Lisp Advent Calendar 2019の11日目の記事です.

この記事のライセンスはCC-BYとします.

この記事は, 10日目の記事の補足になるかもしれない小ネタ記事です.

reduceの使い方の指針について触れます.

使用プログラミング言語は, Common Lispです.
が, JavaScriptのreduce, reduceRightや, Haskellのfoldl, foldrとかも同じだと思うので, もしかしたら参考になるかも.

再掲 10日目の補足 andの展開形

各処理系の実装は参考にしてないけど, 展開系は参考にしました. 1

repl
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)だと思うと,

expanded
(IF (IF (IF T A) B) C)

この形を見ると, reduceで処理できることが分かります.

reduceの使い方 より具体的にのその前に

reduceの使い方の指針を示す前に, 以下の関数を定義しておきます.

reduce-sample.lisp
(defun snoc (list elt)
  (append list (list elt)))

これを使うと, リスト(1 2 3)は, 以下の2パターンで書けます.

repl
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の使い方

上のパターンの,

repl
CL-USER> (snoc (snoc (snoc nil 1) 2) 3)
(1 2 3)

について, この式のsnocをある関数func, nilをある値zと入れ替えたような形,

code
(func (func (func z 1) 2) 3)

で書ける場合は,

reduce-sample.lisp
(reduce #'func '(1 2 3) :initial-value z)

とreduceで書けます.

reduce (from-endオプションがt)

逆に, 下のパターンの,

repl
CL-USER> (cons 1 (cons 2 (cons 3 nil)))
(1 2 3)

について, この式のconsをある関数func, nilをある値zと入れ替えたような形,

code
(func 1 (func 2 (func 3 z)))

で書ける場合は,

reduce-sample.lisp
(reduce #'func '(1 2 3) :initial-value z :from-end t)

:from-endオプションがtのreduceで書けます.

まとめ

reduce難しくないよ.

この記事中の例で使ったリスト(1 2 3)は適当に自分が使いたい場合に読み替えて使ってください.

あと, 数学が好きな人はcatamorphismとか調べてみると幸せになれるかもしれません. 2


  1. SBCL 1.5.9 

  2. 著者もあんまりちゃんとは分かってないので, 優しく教えてくれる人が居ると嬉しい. 

9
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2