Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Gaucheでマクロを書こう

5,140 views

Published on

KMC春合宿2015

Published in: 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 } ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • ..............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 } .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • ..............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 } .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 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 } .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 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 } .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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

×