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

3,541 views

Published on

Introduction to PAPPLY

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,541
On SlideShare
0
From Embeds
0
Number of Embeds
2,880
Actions
Shares
0
Downloads
3
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

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

  1. 1. Before LISPs Just Part of the Past 〜 #7 Partial Application 〜
  2. 2. ものぐさ Lv.1 無名関数便利! lambda万歳!! ※なお、この感覚は発表者の経験に基 づいて構成されており、一般性を著し く欠く可能性があります beginner
  3. 3. ものぐさ Lv.2 関数に名前付けるとか やってらんね lambdalambdalambda... ※後に可読性が確保できていないこ とに気が付いて泣きをみる novice
  4. 4. ものぐさ Lv.3 無名関数は便利だけど、 変数名付けるのも面倒だな ※実は無名関数は使うたびに変数名 を要求する側面があることにようや く気がつく fledgling
  5. 5. ものぐさな僕ら 変数名つけるとか やってらんね fledglingnovice
  6. 6. 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
  7. 7. あまり便利じゃない... ● (defun extension= (ext pathname) (string= (pathname-type pathname) ext)) ● (mapcar (curry #'extension “lisp”) files) ● (mapcar (lambda (pathname) (string= (pathname-type pathname) “lisp”)) files) ● ATOM以外も渡したい
  8. 8. PAPPLY macro 部分適用 + 関数合成 ● プレースホルダ_を使って適用しない引数を表現 – e.g.) (papply (list _ 1)) == (lambda (x) (list x 1)) ● 部分適用する関数の引数には任意のフォームが可能 – フォーム中に_も使える – (papply (equal (pathnane-type _) “lisp”))) == (lambda (x) (equal (pathname-type x) “lisp”))
  9. 9. 可能な形式 ● (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)))
  10. 10. マクロ展開時に環境を見る ● 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なので場合によっては使えない
  11. 11. レキシカル環境に応じた変換 ● (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)))))
  12. 12. 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
  13. 13. P macro ● 特にAPAPPLYが、打ちにくい ● 使い分ける意味はあまりない ● P macro – _が含まれていたらPAPPLYに展開 – Anアナフォラが含まれていたらAPAPPLYに展開 – それ以外はPAPPLYに展開
  14. 14. reader macro for P ... ● 別の種類のカッコを使う – 最近流行っている気がする – brace {} – bracket [] – )を連続させる中で的確に]や}を入れる? ● Clojureだと#() – CLではベクタのリテラル表記用で埋まっている
  15. 15. #' reader macro ● #'list ● #'(lambda (x) (list x))
  16. 16. #' reader macro ● #'list ● #'(lambda (x) (list x)) ここにはlambdaしか書けない → lambda以外のときPに展開する
  17. 17. #' 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
  18. 18. 課題 ● 対応形式が多すぎて無駄 – (p (list (1+ _) 2))の形式しか使ってない ● ネストできない ● MacroやSpecial formを第1引数に取れない – そもそも関数の部分適用 – ANDでREDUCEしたい、とか ● シンボル_が衝突する – こういう目的で使うシンボル専用のパッケージを作るのが汎用的で良いと思う ● it, self, rec, _くらいか – シンボル名での比較が良い解決策だが、受け入れ難い(趣味)

×