before lisps just part of the past ~#7 partial application~

18

Click here to load reader

Upload: samugari

Post on 11-May-2015

3.196 views

Category:

Technology


1 download

DESCRIPTION

Introduction to PAPPLY

TRANSCRIPT

Page 1: Before LISPs Just Part of the Past ~#7 Partial Application~

BeforeLISPs

Just Part of the Past

〜 #7 Partial Application 〜

Page 2: Before LISPs Just Part of the Past ~#7 Partial Application~

ものぐさ Lv.1

無名関数便利!lambda万歳!!

※なお、この感覚は発表者の経験に基づいて構成されており、一般性を著しく欠く可能性があります

beginner

Page 3: Before LISPs Just Part of the Past ~#7 Partial Application~

ものぐさ Lv.2

関数に名前付けるとかやってらんね

lambda lambda lambda ...

※後に可読性が確保できていないことに気が付いて泣きをみる

novice

Page 4: Before LISPs Just Part of the Past ~#7 Partial Application~

ものぐさ Lv.3

無名関数は便利だけど、変数名付けるの も面倒だな

※実は無名関数は使うたびに変数名を要求する側面があることにようやく気がつく

fledgling

Page 5: Before LISPs Just Part of the Past ~#7 Partial Application~

ものぐさな僕ら

変数名つけるとかやってらんね

fledglingnovice

Page 6: Before LISPs Just Part of the Past ~#7 Partial Application~

CURRY● (defun curry (fn &rest args) #'(lambda (&rest args2) (apply fn (append args args2))))

● (defun rcurry (fn &rest args) #'(lambda (&rest args) (apply fn (append args2 args))))

● ANSI Common Lisp 6.6 「関数ビルダ」より引用

● Curry?● Partial Application

Page 7: Before LISPs Just Part of the Past ~#7 Partial Application~

あまり便利じゃない...● (defun extension= (ext pathname) (string= (pathname-type pathname) ext))

● (mapcar (curry #'extension “lisp”) files)● (mapcar (lambda (pathname) (string= (pathname-type pathname) “lisp”)) files)

● ATOM以外も渡したい

Page 8: Before LISPs Just Part of the Past ~#7 Partial Application~

PAPPLY macro部分適用 + 関数合成

● プレースホルダ_を使って適用しない引数を表現

– e.g.)(papply (list _ 1)) == (lambda (x) (list x 1))

● 部分適用する関数の引数には任意のフォームが可能

– フォーム中に_も使える

– (papply (equal (pathnane-type _) “lisp”)))== (lambda (x) (equal (pathname-type x) “lisp”))

Page 9: Before LISPs Just Part of the Past ~#7 Partial Application~

可能な形式● (lambda (x) (list (1+ x) 2))

– (papply (list (1+ _) 2)– (papply #'list (1+ _) 2)– (papply list (1+ _) 2)– (let ((fn #'list)) (papply fn (1+ _) 2))

– (let ((fn #'list)) (papply (fn (1+ _) 2)))

– (papply (#'list (1+ _) 2)))

Page 10: Before LISPs Just Part of the Past ~#7 Partial Application~

マクロ展開時に環境を見る● CLtL2にはいくつかある

– e.g.)VARIABLE-INFORMATION● 束縛の種類、レキシカル束縛されているか、宣言の種類の3値を返す

– ref.) CLtL2 8.5 環境

● ANSI Common Lispでは削除

– :cltl2 feature– SB-CLTL2 package– SB-C::LEXENV-VARS– なお、SBCLのVARIABLE-INFORMATIONの第2値はスペシャル変数に対しては常

にNILなので場合によっては使えない

Page 11: Before LISPs Just Part of the Past ~#7 Partial Application~

レキシカル環境に応じた変換● (defun lexically-bound-p (name env) (or #+sbcl (sb-cltl2:variable-information name env) nil))

● (defmacro papply-listup-format (fn &rest args &environment env) (let* ((gensym-lst) (body (with-tree-leaves ...))) (with-gensyms (not-applied-args) `(lambda (,@(nreverse gensym-lst) &rest ,not-applied-args) (apply ,(if (and (symbolp fn) (not (lexically-bound-p fn env))) `#',fn fn) ,@body ,not-applied-args)))))

Page 12: Before LISPs Just Part of the Past ~#7 Partial Application~

APAPPLY macro● Anaphoric PAPPLY macro● _の代わりにAnの形のアナフォラが使える

– nは0以上の整数

● 引数を2回以上参照したい時はAPAPPLY● (mapcar (apapply (cons a0 (gensym (concat-str (symbol-name a0) "-LST")))

● Clojureの無名関数の短縮構文#()中の%nと同じ

● ref.) Let Over Lambda の #` reader macro

Page 13: Before LISPs Just Part of the Past ~#7 Partial Application~

P macro

● 特にAPAPPLYが、打ちにくい

● 使い分ける意味はあまりない

● P macro– _が含まれていたらPAPPLYに展開

– Anアナフォラが含まれていたらAPAPPLYに展開

– それ以外はPAPPLYに展開

Page 14: Before LISPs Just Part of the Past ~#7 Partial Application~

reader macro for P ...● 別の種類のカッコを使う

– 最近流行っている気がする

– brace {}– bracket []– )を連続させる中で的確に]や}を入れる?

● Clojureだと#()– CLではベクタのリテラル表記用で埋まっている

Page 15: Before LISPs Just Part of the Past ~#7 Partial Application~

#' reader macro

● #'list● #'(lambda (x) (list x))

Page 16: Before LISPs Just Part of the Past ~#7 Partial Application~

#' reader macro

● #'list● #'(lambda (x) (list x))

ここにはlambdaしか書けない

→ lambda以外のときPに展開する

Page 17: Before LISPs Just Part of the Past ~#7 Partial Application~

#' reader macro extension● #'(list (1+ _) x) ; => (p (list (1+ _) x)● (defun |#'-reader| (strm c n) (let ((expr (read strm t nil t))) (if (or (symbolp expr) (eq (car expr) 'cl:lambda)) `(function ,expr) `(p ,@expr))))

● (set-dispatch-macro-character #\# #\' (function |#'-reader|))

● EXTEND-SHARP-QUOTE

Page 18: Before LISPs Just Part of the Past ~#7 Partial Application~

課題● 対応形式が多すぎて無駄

– (p (list (1+ _) 2))の形式しか使ってない

● ネストできない

● MacroやSpecial formを第1引数に取れない

– そもそも関数の部分適用

– ANDでREDUCEしたい、とか

● シンボル_が衝突する

– こういう目的で使うシンボル専用のパッケージを作るのが汎用的で良いと思う

● it, self, rec, _くらいか

– シンボル名での比較が良い解決策だが、受け入れ難い(趣味)