O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Gaucheでマクロを書こう

5.092 visualizações

Publicada em

KMC春合宿2015

Publicada em: Software
  • If you want to download or read this book, Copy link or url below in the New tab ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Doc Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • ..............ACCESS that WEBSITE Over for All Ebooks ................ ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m6jJ5M } .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • ..............ACCESS that WEBSITE Over for All Ebooks ................ ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m6jJ5M } .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • If you want to download or read this book, copy link or url below in the New tab ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes.........ACCESS WEBSITE Over for All Ebooks ..... (Unlimited) ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui

Gaucheでマクロを書こう

  1. 1. GAUCHEでマクロを書こう ID:hnagamin(長嶺英朗) 2015.3.14
  2. 2. 自己紹介 • ID: hnagamin(長嶺英朗) • 京都大学工学部電気電子工学科1回 • 38代会計 • 2014年度の活動 • 競技プログラミング練習会2014 • On Lisp読書会2014 • 関数品評会
  3. 3. 近況 • バイトつらかった • 単位落とした
  4. 4. 今日話すこと • Schemeについて • define-syntax / syntax-rules • define-macro • gensym • マクロを書くときの注意
  5. 5. 今日話さないこと • syntax-case • 継続 • 2種類の変数捕捉 • with-gensymsマクロ • defanaphマクロ
  6. 6. //TODO: 例会講座でsyntax-caseの話をする
  7. 7. この講座の目標 • Schemeに興味を持つ • Gaucheに興味を持つ • Gaucheでマクロが書けるようになる • マクロの力を認識する
  8. 8. 対象 • LISPをあまり書いたことがない/知らない人 • 大学の講義でSchemeを触ったがマクロを書いたことがない人 • LISPerの方はマサカリを用意してください
  9. 9. SCHEMEとは • LISP方言 • 二大方言(Common Lisp / Scheme) • 言語仕様を小さくする努力がなされている • R6RS • 構文スコープを導入したLISP • 継続のサポート
  10. 10. GAUCHEとは • Scheme処理系の一つ • 日本人(川合史朗)が開発 • 独自拡張によってSchemeなのにCommon Lisp的アトモスフィアが 溢れている[要出典]
  11. 11. SCHEMEの文法
  12. 12. 括弧が多い
  13. 13. 括弧は基本的に関数適用 (+ 1 2) (define f (lambda (x y) (+ x y))) (f 1 2) (cons 200 300) (car ‘(l i s p)) (cdr ‘(s c h e m e))
  14. 14. IF文がある (if (> 2 1) (print “2 is larger than 1”) (print “1 is equal or larger than 2”))
  15. 15. 関数がある lambda式で関数が定義できる ((lambda (x y) (list (* x x) (* y y))) 10 20) ;=> (100 400)
  16. 16. 変数が定義できる(1) • (let ((x 100) (y 200)) (print (+ x y))) • let*とかletrecとかもあるよ!
  17. 17. 変数が定義できる(2) (define x 10) (+ x 20) (set! x 10000) (+ x 20)
  18. 18. 繰り返しがある (let loop ((n 7) (value 1)) (if (zero? n) value (loop (- n 1) (* n value)))) 「名前付きlet」という
  19. 19. リストがある (list 1 2 3 4 5) ‘(1 2 3 4 5) 入れ子にもできる ‘(1 2 (3 4 (5)) () (6 7) 8)
  20. 20. S式 アトムまたはS式のリスト
  21. 21. よく見ると、SCHEMEのプログラムは S式そのものである • Schemeプログラムは結局ただのでかいリスト、Schemeプログ ラムはリストが主役 • Schemeプログラムをリストとみなすと、Schemeプログラムを こちゃこちゃするSchemeプログラムがかける
  22. 22. DEFINE-SYNTAX
  23. 23. NIL!マクロ (set! x ‘()) という処理を短く書きたい
  24. 24. NIL!マクロ (set! x ‘()) という処理を短く書きたい 変換前 (nil! x) 変換後 (set! x ‘())
  25. 25. NIL!マクロの実装 (define-syntax nil! (syntax-rules () ((_ x) (set! x ‘()))))
  26. 26. NIL!マクロが書けた • マクロでコードを短く書けた • 短く書くことで、本来人間が気にするべきだった部分をマク ロに任せることができ、人間はよりプログラムの高次の部分 について考えることができるようになった
  27. 27. INCFマクロ • 変数に格納されてい る数を指定された数 だけ増加させる • 増分が省略されてい る場合は1だけ増やす (define x 100) (incf x 49) x ;=> 149 (incf x) x ;=> 150
  28. 28. INCFマクロ (define-syntax incf (syntax-rules () ((_ x) (set! x (+ x 1)) ((_ x var) (set! x (+ x var))))
  29. 29. FOR文を書きたい (for (i 1 10) (print i) (print (* 2 i)) みたいな感じで書きたい
  30. 30. FOR文をどう展開するか (for (i 1 10) (print i) (print (* 2 i)) (for-each (lambda (i) (print i) (print (* 2 i)) (nanika 1 10))
  31. 31. FORマクロの実装 (define (range from to) (if (>= from to) (list from) (cons from (range (+ 1 from) to)))) ;(range 1 5) => (1 2 3 4 5)
  32. 32. FORマクロの実装 (define (range from to) (if (>= from to) (list from) (cons from (range (+ 1 from) to)))) (define-syntax for (syntax-rules () ((_ (i a b) body ...) (for-each (lambda (i) body ...) (range a b)))))
  33. 33. 追加仕様 (for (i from 1 to 10) (print (* i i))) みたいに書きたい
  34. 34. FOR文(改訂) (define-syntax for (syntax-rules (from to) ((_ (i a b) body ...) (for-each (lambda (i) body ...) (range a b))) ((_ (i from a to b) body ...) (for (i a b) body ...))))
  35. 35. FOR文(改訂) (define-syntax for (syntax-rules (from to) ((_ (i a b) body ...) (for-each (lambda (i) body ...) (range a b))) ((_ (i from a to b) body ...) (for (i a b) body ...))))
  36. 36. FOR文(改訂) 完璧
  37. 37. FOR文(改訂) 完璧(完璧ではない)
  38. 38. どこが良くない? (define-syntax for (syntax-rules (from to) ((_ (i a b) body ...) (for-each (lambda (i) body ...) (range a b))) ((_ (i from a to b) body ...) (for (i a b) body ...))))
  39. 39. どこが良くない? (define-syntax for (syntax-rules (from to) ((_ (i a b) body ...) (for-each (lambda (i) body ...) (range a b))) ((_ (i from a to b) body ...) (for (i a b) body ...))))
  40. 40. YOKUNAI (for (i 1 500000000) (print i))
  41. 41. YOKUNAI (for-each (lambda (i) (print i)) (range 1 500000000))
  42. 42. YOKUNAI (for-each (lambda (i) (print i)) (range 1 500000000)) このコードは500000000要素のリストを生成する
  43. 43. このコードは500000000要素のリストを生成する
  44. 44. DEFINE-MACRO
  45. 45. DEFINE-MACROで FOR文の書き直し • define-macroはGaucheの独自拡張 • define-macroでCommon Lispのマクロ並みの強さを持つマク ロを書くことができる • やってることはほぼ関数と同じ • コンパイル時にS式を引数に受け取って評価し、S式を返す。 返されたS式はプログラム中に埋め込まれる
  46. 46. FOR文(二訂) (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind))) `(let loop ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (loop (+ 1 ,i)))))))
  47. 47. なにこれ
  48. 48. バッククオート記法 S式を分かりやすく書くときに使える記法 `と,と,@を使う
  49. 49. バッククオート記法のルール 頭に ` をつけられた式は評価しない ただし、頭に , をつけられた式は評価する ,@をつけられた式は評価した後括弧を外す `(x ,y) 評価しない 評価する
  50. 50. 練習問題
  51. 51. 練習問題 (define x 20) (define y 30) `(+ x y) ;=> (+ x y)
  52. 52. 練習問題 (define x 20) (define y 30) `(+ ,x ,y) ;=> (+ 20 30)
  53. 53. 練習問題 (define x 20) (define y ‘(30 40)) `(x ,@y) ;=> (20 30 40)
  54. 54. 練習問題 (define x 20) (define y 30) `(,(+ x y) (+ x y) (+ x ,y) ,@(cons `(,x ,y) (+ x y))) ;=> (50 (+ x y) (+ x 30) (20 30) . 50)
  55. 55. 何の話だっけ
  56. 56. FOR文(二訂) (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind))) `(let loop ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (loop (+ 1 ,i)))))))
  57. 57. FOR文(二訂) 完璧
  58. 58. FOR文(二訂) 完璧(完璧ではない)
  59. 59. どこが良くない? (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind))) `(let loop ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (loop (+ 1 ,i)))))))
  60. 60. どこが良くない? (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind))) `(let loop ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (loop (+ 1 ,i)))))))
  61. 61. YOKUNAI (for (loop 1 5) (print loop)) ; このコードは1, 2, 3, 4, 5を表示してほしい
  62. 62. YOKUNAI (let loop ((loop 1)) (if (>= loop 5) (begin (print loop)) (begin (print loop) (loop (+ 1 loop)))))
  63. 63. YOKUNAI (let loop ((loop 1)) (if (>= loop 5) (begin (print loop)) (begin (print loop) (loop (+ 1 loop))))) invalid application: (1 2)
  64. 64. 良くない解決策 (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind))) `(let asjdiwoqwe ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (asjdiwoqwe (+ 1 ,i)))))))
  65. 65. 変数捕捉 • マクロが意図とは異なる環境の変数を参照すること • 捕捉には2種類ある • define-syntaxは変数捕捉を起こさない「健全なマクロ (Hygienic macro)」だが、変数捕捉を起こしうるマクロより記 述力が弱い • define-macroは変数捕捉を起こしうるマクロでありdefine- syntaxより記述力が強いが、たまに変数捕捉でえげつない問 題を生じうる
  66. 66. GENSYM • シンボルを生成する • ここで生成されたシンボルは、ソースコード中に出てくる他 のどのシンボルとも等しくないことが保障されている
  67. 67. GENSYMの使用例 (gensym) ;=> #:G100 (gensym) ;=> #:G101
  68. 68. FOR文(三訂) (define-macro (for bind . body) (let ((i (car bind)) (from (cadr bind)) (to (caddr bind)) (loop (gensym))) `(let ,loop ((,i ,from)) (if (>= ,i ,to) (begin ,@body) (begin ,@body (,loop (+ 1 ,i)))))))
  69. 69. AIFマクロ (define *table* ‘((1 one) (2 two) (3 three))) (print (aif (assoc 1 *table*) (car (cdr it)) “Not Found”)))
  70. 70. AIFマクロ • aifは条件節の返す値をitに束 縛して、then節とelse節で使 えるようにする • 変数捕捉をうまく用いている (define *table* ‘((1 one) (2 two) (3 three))) (print (aif (assoc 1 *table*) (car (cdr it)) “Not Found”))) 【alist】 ((key1 value1) (key2 value2) …) の形のリスト 連想配列っぽく使える 【assoc】 (assoc key alist) alist中からkeyを探す。 keyが存在したら(key value)を返す。 さもなくば#fを返す。
  71. 71. AIFマクロ • aifは条件節の返す値をitに束 縛して、then節とelse節で使 えるようにする • 変数捕捉をうまく用いている (define *table* ‘((1 one) (2 two) (3 three))) (print (aif (assoc 1 *table*) (car (cdr it)) “Not Found”)))
  72. 72. 実装 (define-macro (aif predicate then-clause else-clause) `(let ((it ,predicate)) (if it ,then-clause ,else-clause)))
  73. 73. まとめ • Gaucheには2種類のマクロがある • 健全なマクロ/健全でないマクロ • マクロをうまく用いるとソースコードを短く簡潔にできる • マクロ定義を慎重に行わないと、たまにえげつない問題を起 こしうる
  74. 74. 関数品評会
  75. 75. 関数品評会 • 7月から関数品評会に参加しました • 関数品評会 • 品評会で発表したマクロを紹介します
  76. 76. アリティの固定 (define 1- (cut - <> 1)) (define (repeat n fn) (let loop ((m n) (x '())) (if (= m 0) x (loop (1- m) (cons (fn) x))))) (define-macro (*-ary n fn) (let ((args (repeat n gensym))) `(lambda ,args (,fn ,@args)))) ; (arity (*-ary 4 +)) ; => 4
  77. 77. グローバル関数を使わない 非決定性オペレータ https://gist.github.com/1995hnagamin/252ed5638a0977205f03

×