kikkiiのブログ

ひきこもり

(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)