(ql:quickload :arrow-macros :silent t)
Common Lispのライブラリをインストールするとき
(ql:quickload :ライブラリ名)
とすると
To load "ライブラリ名": Load 1 ASDF system: alexandria ; Loading "ライブラリ名"
とかって吐くので、それを黙らせるために
(ql:quickload :ライブラリ名 :silent t)
とすればいいのだと気づくのに何時間も費やしてしまった。
で、arrow-macrosってライブラリ、よさそう。気に入った。arrow-macrosを使った方が読みやすい気がする。
;;arrow-macrosを使う > (ql:quickload :arrow-macros :silent t) > (use-package :arrow-macros) ;;通常の書き方 > (tan (cos (sin 1))) 0.7863574 ;;arrow-macrosを使う > (->> 1 (sin) (cos) (tan)) 0.7863574
;;2の5乗 > (expt 2 5) 32 ;;0.7863574の5乗 > (expt (tan (cos (sin 1))) 5) 0.3006768 ;;arrow-macrosを使って0.7863574の5乗 > (-<>> 1 (sin) (cos) (tan) (expt <> 5)) 0.3006768
;;通常の書き方 > (tan (cos (sin (tan (cos (sin 1)))))) 0.9500785 ;;arrow-macrosを使う > (->> 1 (sin) (cos) (tan) (sin) (cos) (tan)) 0.9500785
;;通常の書き方 > (expt (tan (cos (sin (expt (tan (cos (sin 1))) 5)))) 5) 5.7260404 ;;arrow-macrosを使う > (-<>> 1 (sin) (cos) (tan) (expt <> 5) (sin) (cos) (tan) (expt <> 5)) 5.7260404
この最後のは明らかにarrow-macrosの方が読みやすく私には思える。それと、sin, cos, tanのところ...カリー化されているって言えばいいのか...変数が1つだとカリー化と呼べないのかもしれないが...そこがまたいいな、と感じる。次のようにカリー化されていない風(?)にも書ける。
> (-<>> 1 (sin <>) (cos <>) (tan <>) (expt <> 5) (sin <>) (cos <>) (tan <>) (expt <> 5)) 5.7260404
2つの引数を持つ関数でもやってみる。
> (->> 2 (expt 2) (expt 2) (expt 2)) 65536 > (-<>> 2 (expt 2 <>) (expt 2 <>) (expt 2 <>)) 65536
関数合成する感じで使ってみる。
;;alexandriaに入っているcomposeを使って関数合成したい > (ql:quickload :alexandria) > (import '(alexandria:compose)) ;;composeを使って関数合成 > (funcall (compose #'tan #'cos #'sin) 1) 0.7863574 > (mapcar (compose #'tan #'cos #'sin) '(1 2 3 4 5)) (0.7863574 0.70533913 1.523873 0.88959223 0.64719504) ;;arrow-macrosを使って関数合成 > ((lambda (x) (->> x (sin) (cos) (tan))) 1) 0.7863574 > (mapcar (lambda (x) (->> x (sin) (cos) (tan))) '(1 2 3 4 5)) (0.7863574 0.70533913 1.523873 0.88959223 0.64719504)
どちらが読みやすいかは微妙。だけどarrow-macrosの方は関数の前に#'をつけなくてもいいので、そこはよい。
次のように関数合成するための関数をlambdaを使って新しくつくらなければなければならないときは、arrow-macrosの方がリーダブルだと私は感じる。
> (mapcar (compose (lambda (x) (* x x x)) (lambda (x) (* x x))) '(1 2 3 4 5)) (1 64 729 4096 15625) > (mapcar (lambda (x) (-<>> x (* <> <>) (* <> <> <>))) '(1 2 3 4 5)) (1 64 729 4096 15625)