[library] f-underscore

Weblocksで使っているライブラリの中身も、それなりに見ることが多くなってきたので纏めようと思ったのでした。たぶん、すぐに挫折します。

f-underscoreは lambdaを少ないタイプ数で記述するためのマクロを持ったユーティリティです。引数の数や種類などで複数種類が存在します。

f

通常のlambdaとほぼ同じ使い方。基本的にlambdaと打つ代わりに、fになっただけ。

CL-USER> (macroexpand-1 '(f (x y)
                           (* x y)))
; (LAMBDA (X Y) (* X Y))

f0

引数が0個のlambda。

CL-USER> (macroexpand-1 '(f0 (gethash :fuga *hoge-hash*)))
; (LAMBDA () (GETHASH :FUGA *HOGE-HASH*))

f_

引数が1個のlambda。引数は _ に束縛されている。

CL-USER> (macroexpand-1 '(f_ (* _ _)))
; (LAMBDA (_) (* _ _))

f_n

引数を &restで受け取るlambda。引数は _に束縛されている。

CL-USER> (macroexpand-1 '(f_n (format t "~{~A~^,~}" _)))
; (LAMBDA (&REST _) (FORMAT T "~{~A~^,~}" _))

f_%

引数を &restで受けるが、使用しないlambda。

CL-USER> (macroexpand-1 '(f_% (format t "Hello, world")))
; (LAMBDA (&REST #:|ignore1178|)
;  (DECLARE (IGNORE #:|ignore1178|))
;  (FORMAT T "Hello, world"))

パッと有用な使い方が思いつかなかったけど、関数に渡すための関数の場合には引数を無視したい状況は、ある、かな。

m

どう使うのだろう、これ。とりあえず、こんな感じで展開されます。

CL-USER> (macroexpand-1 '(m (arg &rest body)
                           "DocString."
                           `(lambda ,args ,@body)))
; (LAMBDA (&REST #:|macro-lambda-list1183|)
;   "DocString."
;   (DESTRUCTURING-BIND
;       (ARG &REST BODY)
;       #:|macro-lambda-list1183|
;     `(LAMBDA ,ARGS ,@BODY)))

f-underscore.lispのコメントには

;   (setf (macro-function 'foo) (m args ..)) ~= (defmacro foo args ..)

と書かれているのですが、、、

全体を通して

f-underscore のマクロ全てに言えることですが、lambdaとの大きな違いとして括弧の先頭、関数として評価される位置に置くことが出来ないようです。

CL-USER> ((lambda (x) (1+ x)) 1)
; 2
CL-USER> ((f_ (1+ _)) 1)
; in: LAMBDA NIL
;     ((F-UNDERSCORE:F_
;        (1+ F-UNDERSCORE:_))
;      1)
; 
; caught ERROR:
;   illegal function call
; 
; compilation unit finished
;   caught 1 ERROR condition

lambdaは特別なんですね。λかわいいよλ。