SlideShare una empresa de Scribd logo
1 de 44
Descargar para leer sin conexión
 Macros in Clojure
      @athos0220
Agenda

• Lispマクロ入門
• Clojureのマクロとその周辺
• Clojureマクロの応用例
 Lispマクロ入門
マクロとは
                when                                       if



      =        print    print          =                   do            nil



mod       0    "Fizz"   "Buzz"   mod         0    print         print



 x        15                      x         15    "Fizz"        "Buzz"


                                           (if (= (mod x 15) 0)
(when (= (mod x 15) 0)                       (do
  (print “Fizz”)                               (print “Fizz”)
  (print “Buzz”))                              (print “Buzz”))
                                             nil)

             構文木を組み替えるための仕組み
           →自由に構文を作ることができる仕組み
マクロの定義
• シンボルやリストで展開形のコードを
 作ってやる
  (when ⃝⃝   (if ⃝⃝
    △△         (do △△
    ✕✕)             ✕✕)
               nil)
マクロの定義
    • シンボルやリストで展開形のコードを
       作ってやる
           (when ⃝⃝            (if ⃝⃝
             △△                  (do △△
             ✕✕)                      ✕✕)
                                 nil)
(defmacro when [test & body]
  (list ’if
        test
        (cons ’do body)
        nil))
マクロの定義
    • シンボルやリストで展開形のコードを
       作ってやる
           (when ⃝⃝              (if ⃝⃝
             △△                    (do △△
             ✕✕)                        ✕✕)
                                   nil)
(defmacro when [test & body]   (defmacro when [test & body]
  (list ’if                      `(if ~test
        test                        (do ~@body)
        (cons ’do body)             nil)
        nil))
名前衝突の問題
名前衝突の問題
束縛変数の衝突   自由変数の衝突
名前衝突の問題
束縛変数の衝突                  自由変数の衝突
     (defmacro or [expr1 expr2]
       `(let [val ~expr1]
          (if val
            val
            ~expr2)))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]
  (or false val))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]
  (or false val))


(let [val true]
  (let [val false]
    (if val
      val
      val))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]
  (or false val))


(let [val true]
  (let [val false]
    (if val
      val
      val))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]
  (or false val))


(let [val true]
  (let [val false]
    (if val
      val
      val))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]                  (let [let nil]
  (or false val))                  (or false true))


(let [val true]
  (let [val false]
    (if val
      val
      val))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]                  (let [let nil]
  (or false val))                  (or false true))


(let [val true]                 (let [let nil]
  (let [val false]                (let [val false]
    (if val                         (if val
      val                             val
      val))                           true))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]                  (let [let nil]
  (or false val))                  (or false true))


(let [val true]                 (let [let nil]
  (let [val false]                (let [val false]
    (if val                         (if val
      val                             val
      val))                           true))
名前衝突の問題
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val ~expr1]
                   (if val
                     val
                     ~expr2)))
(let [val true]                  (let [let nil]
  (or false val))                  (or false true))


(let [val true]                 (let [let nil]
  (let [val false]                (let [val false]
    (if val                         (if val
      val                             val
      val))                           true))
健全なマクロ (Hygienic macros)

• 名前の衝突を自動的に回避してくれる
  ハイパーなマクロ
健全なマクロ (Hygienic macros)

   • 名前の衝突を自動的に回避してくれる
     ハイパーなマクロ
(define-syntax or
  (syntax-rules ()
   ((or expr1 expr2)
    (let ([val expr1])
      (if val
        val
        expr2)))))
健全なマクロ (Hygienic macros)

   • 名前の衝突を自動的に回避してくれる
     ハイパーなマクロ
(define-syntax or        (let ([val true])
  (syntax-rules ()         (or false val))
   ((or expr1 expr2)
    (let ([val expr1])
      (if val
        val
        expr2)))))
健全なマクロ (Hygienic macros)

   • 名前の衝突を自動的に回避してくれる
     ハイパーなマクロ
(define-syntax or        (let ([val true])
  (syntax-rules ()         (or false val))
   ((or expr1 expr2)
    (let ([val expr1])
      (if val            (let ([val true])
        val                (let ([val_0 false])
        expr2)))))           (if val_0
                               val_0
                               val)))
マクロの分類
• 高レベル:専用のパターン言語をもつ
• 低レベル:Lispの関数でコードを操作する
          低レベル                 高レベル
不
健 • 伝統的なマクロ
全

健 • syntactic closures
  • explicit renaming    • syntax-rules
全 • syntax-case
マクロの分類
• 高レベル:専用のパターン言語をもつ
• 低レベル:Lispの関数でコードを操作する
          低レベル                 高レベル
不
健 • 伝統的なマクロ
全
                     >
健 • syntactic closures
  • explicit renaming    • syntax-rules
全 • syntax-case
マクロの分類
• 高レベル:専用のパターン言語をもつ
• 低レベル:Lispの関数でコードを操作する
          低レベル                 高レベル
不
健 • 伝統的なマクロ
全
            >
                     >
健 • syntactic closures
  • explicit renaming    • syntax-rules
全 • syntax-case
 Clojureの
マクロシステムとその周辺
Clojureのマクロシステム


• 伝統的なマクロがベース
                              低レベル                   高レベル


                     不
                     健   • 伝統的なマクロ
                     全




                               >
• syntax-quote が特徴


                                          >
                     健   • syntactic closures
                         • explicit renaming    • syntax-rules
                     全   • syntax-case
syntax-quote
syntax-quote
束縛変数の衝突    自由変数の衝突
syntax-quote
束縛変数の衝突                  自由変数の衝突
     (defmacro or [expr1 expr2]
       `(let [val# ~expr1]
          (if val#
            val#
            ~expr2)))
syntax-quote
束縛変数の衝突                         自由変数の衝突
            (defmacro or [expr1 expr2]
              `(let [val# ~expr1]
                 (if val#
 syntax-quote      val#
                   ~expr2)))
syntax-quote
束縛変数の衝突                           自由変数の衝突
              (defmacro or [expr1 expr2]
                `(let [val# ~expr1]
                   (if val#
   syntax-quote      val#
                     ~expr2)))
(let [val true]
  (or false val))
syntax-quote
        束縛変数の衝突                                自由変数の衝突
                        (defmacro or [expr1 expr2]
                          `(let [val# ~expr1]
                             (if val#
             syntax-quote      val#
                               ~expr2)))
          (let [val true]
            (or false val))



(let [val true]
  (clojure.core/let [val__419__auto__ false]
    (if val__419__auto__
      val__419__auto__
      val))

#をつけた名前を自動でリネーム (auto-gensym)
syntax-quote
        束縛変数の衝突                                自由変数の衝突
                        (defmacro or [expr1 expr2]
                          `(let [val# ~expr1]
                             (if val#
             syntax-quote      val#
                               ~expr2)))
          (let [val true]                     (let [let nil]
            (or false val))                     (or false true))



(let [val true]
  (clojure.core/let [val__419__auto__ false]
    (if val__419__auto__
      val__419__auto__
      val))

#をつけた名前を自動でリネーム (auto-gensym)
syntax-quote
        束縛変数の衝突                                         自由変数の衝突
                        (defmacro or [expr1 expr2]
                          `(let [val# ~expr1]
                             (if val#
             syntax-quote      val#
                               ~expr2)))
          (let [val true]                     (let [let nil]
            (or false val))                     (or false true))



(let [val true]                                (let [let nil]
  (clojure.core/let [val__419__auto__ false]     (clojure.core/let [val__419__auto__ false]
    (if val__419__auto__                           (if val__419__auto__
      val__419__auto__                               val__419__auto__
      val))                                          true))

#をつけた名前を自動でリネーム (auto-gensym) その他の名前にはnamespace名をqualifyする
メタデータ
    •   ほとんどすべてのオブジェクトにメタデータを付加できる

    •   Clojureではコードもデータ

        →コードのほとんどあらゆる部分にメタデータをアノテー
         ションとして付加できる
                                 名前をnamespaceにプライベートにする
               (defn ^:private f [x] x)

               (def ^:dynamic x nil)
動的スコープの変数にする                            戻り値と引数の型ヒント
               (defn fact ^long [^long x]
                 (if (= x 0)
                   1
                   (* x (fact (- x 1)))))
Java Interop

• ClojureからJavaのクラスにアクセスできる
• Clojureは大部分がJavaで書かれている
• Javaで書かれているClojureのコンパイラ自
 体や内部で使われる構文木にも触れる
暗黙の引数 &formと&env

• マクロ呼出しのフォームを囲むコンテ
 キストに関する情報が渡ってくる

 -   &form:マクロ呼出しのフォーム全体

 -   &env:マクロ呼出しの時点で見えて
     いるローカル環境
 Clojure
マクロの応用例
the オペレータ   http://d.hatena.ne.jp/athos/20120129/THE_operator_in_clojure




   •   「型を1つ引数にとり現在のスコープに唯一存
       在するその型のオブジェクトを返す演算子」
       by @kinaba
   •   &envを使って、そのスコープで見えている変
       数のうち、指定した型がメタデータに付いて
       いるものを拾ってくる
(let [^File _ (File. "foo.txt")
      ^FileReader __ (FileReader. (the File))
      ^BufferedReader ___ (BufferedReader (the FileReader))]
  (.readLine (the BufferedReader)))
inline assembler マクロ                         http://www.slideshare.net/sohta/shibuyalisp-tt7




         • Clojureコンパイラが使うバイトコード
              生成ライブラリをマクロ展開時に使う
(def fact                                            public final java.lang.Object invoke(java.lang.
  (fn-iasm [n]                                         Code:
    (aload_1)                                           Stack=2, Locals=6, Args_size=2
    (checkcast Integer)                                 0:   aload_1
    (invokevirtual ^int Integer/intValue [])            1:   checkcast      #25; //class java/lang/I
    (istore_2)                                          4:   invokevirtual #29; //Method java/lang/
    (iconst_1)                                          7:   istore_2
    (istore_3)                                          8:   iconst_1
    :loop                                               9:   istore_3
    (iload_2)                                           10: iload_2
    (ifeq :end)                                         11: ifeq      24
    (ilaod_2)                                           14: iload_2
    (iload_3)                                           15: iload_3
    (imul)                                              16: imul
    (istore_3)                                          17: istore_3
    (iinc 2 -1)                                         18: iinc      2, -1
    (goto :loop)                                        21: goto      10
    :end                                                24: iload_3
    (iload_3)                                           25: invokestatic    #33; //Method java/lang/
    (invokestatic ^Integer Integer/valueOf [int])       28: areturn
    (areturn)))
syntactic-closure
                        http://d.hatena.ne.jp/athos/20120506/syntactic_closure_in_clojure



•   syntactic closuresによる健全なマクロを定義で
    きるようにするライブラリ
                                                                  低レベル              高レベル


•   syntax-quoteで定義できない                                  不
                                                         健
                                                         全
                                                             • 伝統的なマクロ


    ある種のマクロが定義可能に
                                                             • syntactic closures
(define-syntax or [expr1 expr2]           健
                                             • explicit renaming • syntax-rules
                                          全  • syntax-case
  (sc-macro-transformer
    (fn [env]
      (quasiquote
        (let [val ~(make-syntactic-closure env nil expr1)]
          (if val
            val
            ~(make-syntactic-closure env nil expr2)))))))

(let [val true]                       (let [val true]
  (or false val))                       (let [val396 false]
                                          (if val396 val396 val))
 まとめ

• Clojureのマクロ周りには遊べるおも
 ちゃがたくさん

• アイデア次第で貢献できる可能性?
• nagoya-lispに参加しましょう
おわり

Más contenido relacionado

Destacado

A little exercise with clojure macro
A little exercise with clojure macroA little exercise with clojure macro
A little exercise with clojure macroZehua Liu
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsしてmitsutaka mimura
 
Clojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMClojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMsunng87
 
入門ClojureScript
入門ClojureScript入門ClojureScript
入門ClojureScriptsohta
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Leonardo Borges
 
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...AboutYouGmbH
 
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なものClojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なものsohta
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)Jacek Laskowski
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例sohta
 
Clojure from ground up
Clojure from ground upClojure from ground up
Clojure from ground upDi Xu
 
アルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するアルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するAtCoder Inc.
 

Destacado (19)

A little exercise with clojure macro
A little exercise with clojure macroA little exercise with clojure macro
A little exercise with clojure macro
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして
 
Patterns
PatternsPatterns
Patterns
 
A Dive Into Clojure
A Dive Into ClojureA Dive Into Clojure
A Dive Into Clojure
 
Clojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMClojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVM
 
Writing Macros
Writing MacrosWriting Macros
Writing Macros
 
入門ClojureScript
入門ClojureScript入門ClojureScript
入門ClojureScript
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012
 
Clojure的魅力
Clojure的魅力Clojure的魅力
Clojure的魅力
 
Clojure概览
Clojure概览Clojure概览
Clojure概览
 
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
 
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なものClojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
Clojureシンタックスハイライター開発から考えるこれからのlispに必要なもの
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
Clojure: a LISP for the JVM
Clojure: a LISP for the JVMClojure: a LISP for the JVM
Clojure: a LISP for the JVM
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
DSL in Clojure
DSL in ClojureDSL in Clojure
DSL in Clojure
 
プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例
 
Clojure from ground up
Clojure from ground upClojure from ground up
Clojure from ground up
 
アルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するアルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化する
 

Más de sohta

入門Transducers
入門Transducers入門Transducers
入門Transducerssohta
 
Clojure Language Update (2015)
Clojure Language Update (2015)Clojure Language Update (2015)
Clojure Language Update (2015)sohta
 
入門core.async
入門core.async入門core.async
入門core.asyncsohta
 
REPLライフをもっと快適に
REPLライフをもっと快適にREPLライフをもっと快適に
REPLライフをもっと快適にsohta
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターsohta
 
ClojureではじめるSTM入門
ClojureではじめるSTM入門ClojureではじめるSTM入門
ClojureではじめるSTM入門sohta
 
Clojureによるバイトコードプログラミング
ClojureによるバイトコードプログラミングClojureによるバイトコードプログラミング
Clojureによるバイトコードプログラミングsohta
 

Más de sohta (7)

入門Transducers
入門Transducers入門Transducers
入門Transducers
 
Clojure Language Update (2015)
Clojure Language Update (2015)Clojure Language Update (2015)
Clojure Language Update (2015)
 
入門core.async
入門core.async入門core.async
入門core.async
 
REPLライフをもっと快適に
REPLライフをもっと快適にREPLライフをもっと快適に
REPLライフをもっと快適に
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
 
ClojureではじめるSTM入門
ClojureではじめるSTM入門ClojureではじめるSTM入門
ClojureではじめるSTM入門
 
Clojureによるバイトコードプログラミング
ClojureによるバイトコードプログラミングClojureによるバイトコードプログラミング
Clojureによるバイトコードプログラミング
 

Último

「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-LoopへTetsuya Nihonmatsu
 
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見Shumpei Kishi
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法ssuser370dd7
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~arts yokohama
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdfAyachika Kitazaki
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)ssuser539845
 
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfMatsushita Laboratory
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor arts yokohama
 
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦Sadao Tokuyama
 

Último (12)

「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
 
2024 04 minnanoito
2024 04 minnanoito2024 04 minnanoito
2024 04 minnanoito
 
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
 
What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
 
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor
 
2024 03 CTEA
2024 03 CTEA2024 03 CTEA
2024 03 CTEA
 
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
 

Macros in Clojure

  • 1.  Macros in Clojure @athos0220
  • 4. マクロとは when if = print print = do nil mod 0 "Fizz" "Buzz" mod 0 print print x 15 x 15 "Fizz" "Buzz" (if (= (mod x 15) 0) (when (= (mod x 15) 0) (do (print “Fizz”) (print “Fizz”) (print “Buzz”)) (print “Buzz”)) nil) 構文木を組み替えるための仕組み →自由に構文を作ることができる仕組み
  • 5. マクロの定義 • シンボルやリストで展開形のコードを 作ってやる (when ⃝⃝ (if ⃝⃝ △△ (do △△ ✕✕) ✕✕) nil)
  • 6. マクロの定義 • シンボルやリストで展開形のコードを 作ってやる (when ⃝⃝ (if ⃝⃝ △△ (do △△ ✕✕) ✕✕) nil) (defmacro when [test & body] (list ’if test (cons ’do body) nil))
  • 7. マクロの定義 • シンボルやリストで展開形のコードを 作ってやる (when ⃝⃝ (if ⃝⃝ △△ (do △△ ✕✕) ✕✕) nil) (defmacro when [test & body] (defmacro when [test & body] (list ’if `(if ~test test (do ~@body) (cons ’do body) nil) nil))
  • 10. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2)))
  • 11. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (or false val))
  • 12. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (or false val)) (let [val true] (let [val false] (if val val val))
  • 13. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (or false val)) (let [val true] (let [val false] (if val val val))
  • 14. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (or false val)) (let [val true] (let [val false] (if val val val))
  • 15. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (let [val false] (if val val val))
  • 16. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (let [let nil] (let [val false] (let [val false] (if val (if val val val val)) true))
  • 17. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (let [let nil] (let [val false] (let [val false] (if val (if val val val val)) true))
  • 18. 名前衝突の問題 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val ~expr1] (if val val ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (let [let nil] (let [val false] (let [val false] (if val (if val val val val)) true))
  • 19. 健全なマクロ (Hygienic macros) • 名前の衝突を自動的に回避してくれる ハイパーなマクロ
  • 20. 健全なマクロ (Hygienic macros) • 名前の衝突を自動的に回避してくれる ハイパーなマクロ (define-syntax or (syntax-rules () ((or expr1 expr2) (let ([val expr1]) (if val val expr2)))))
  • 21. 健全なマクロ (Hygienic macros) • 名前の衝突を自動的に回避してくれる ハイパーなマクロ (define-syntax or (let ([val true]) (syntax-rules () (or false val)) ((or expr1 expr2) (let ([val expr1]) (if val val expr2)))))
  • 22. 健全なマクロ (Hygienic macros) • 名前の衝突を自動的に回避してくれる ハイパーなマクロ (define-syntax or (let ([val true]) (syntax-rules () (or false val)) ((or expr1 expr2) (let ([val expr1]) (if val (let ([val true]) val (let ([val_0 false]) expr2))))) (if val_0 val_0 val)))
  • 23. マクロの分類 • 高レベル:専用のパターン言語をもつ • 低レベル:Lispの関数でコードを操作する 低レベル 高レベル 不 健 • 伝統的なマクロ 全 健 • syntactic closures • explicit renaming • syntax-rules 全 • syntax-case
  • 24. マクロの分類 • 高レベル:専用のパターン言語をもつ • 低レベル:Lispの関数でコードを操作する 低レベル 高レベル 不 健 • 伝統的なマクロ 全 > 健 • syntactic closures • explicit renaming • syntax-rules 全 • syntax-case
  • 25. マクロの分類 • 高レベル:専用のパターン言語をもつ • 低レベル:Lispの関数でコードを操作する 低レベル 高レベル 不 健 • 伝統的なマクロ 全 > > 健 • syntactic closures • explicit renaming • syntax-rules 全 • syntax-case
  • 27. Clojureのマクロシステム • 伝統的なマクロがベース 低レベル 高レベル 不 健 • 伝統的なマクロ 全 > • syntax-quote が特徴 > 健 • syntactic closures • explicit renaming • syntax-rules 全 • syntax-case
  • 29. syntax-quote 束縛変数の衝突 自由変数の衝突
  • 30. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# val# ~expr2)))
  • 31. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# syntax-quote val# ~expr2)))
  • 32. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# syntax-quote val# ~expr2))) (let [val true] (or false val))
  • 33. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# syntax-quote val# ~expr2))) (let [val true] (or false val)) (let [val true] (clojure.core/let [val__419__auto__ false] (if val__419__auto__ val__419__auto__ val)) #をつけた名前を自動でリネーム (auto-gensym)
  • 34. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# syntax-quote val# ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (clojure.core/let [val__419__auto__ false] (if val__419__auto__ val__419__auto__ val)) #をつけた名前を自動でリネーム (auto-gensym)
  • 35. syntax-quote 束縛変数の衝突 自由変数の衝突 (defmacro or [expr1 expr2] `(let [val# ~expr1] (if val# syntax-quote val# ~expr2))) (let [val true] (let [let nil] (or false val)) (or false true)) (let [val true] (let [let nil] (clojure.core/let [val__419__auto__ false] (clojure.core/let [val__419__auto__ false] (if val__419__auto__ (if val__419__auto__ val__419__auto__ val__419__auto__ val)) true)) #をつけた名前を自動でリネーム (auto-gensym) その他の名前にはnamespace名をqualifyする
  • 36. メタデータ • ほとんどすべてのオブジェクトにメタデータを付加できる • Clojureではコードもデータ →コードのほとんどあらゆる部分にメタデータをアノテー ションとして付加できる 名前をnamespaceにプライベートにする (defn ^:private f [x] x) (def ^:dynamic x nil) 動的スコープの変数にする 戻り値と引数の型ヒント (defn fact ^long [^long x] (if (= x 0) 1 (* x (fact (- x 1)))))
  • 37. Java Interop • ClojureからJavaのクラスにアクセスできる • Clojureは大部分がJavaで書かれている • Javaで書かれているClojureのコンパイラ自 体や内部で使われる構文木にも触れる
  • 38. 暗黙の引数 &formと&env • マクロ呼出しのフォームを囲むコンテ キストに関する情報が渡ってくる - &form:マクロ呼出しのフォーム全体 - &env:マクロ呼出しの時点で見えて いるローカル環境
  • 40. the オペレータ http://d.hatena.ne.jp/athos/20120129/THE_operator_in_clojure • 「型を1つ引数にとり現在のスコープに唯一存 在するその型のオブジェクトを返す演算子」 by @kinaba • &envを使って、そのスコープで見えている変 数のうち、指定した型がメタデータに付いて いるものを拾ってくる (let [^File _ (File. "foo.txt") ^FileReader __ (FileReader. (the File)) ^BufferedReader ___ (BufferedReader (the FileReader))] (.readLine (the BufferedReader)))
  • 41. inline assembler マクロ http://www.slideshare.net/sohta/shibuyalisp-tt7 • Clojureコンパイラが使うバイトコード 生成ライブラリをマクロ展開時に使う (def fact public final java.lang.Object invoke(java.lang. (fn-iasm [n] Code: (aload_1) Stack=2, Locals=6, Args_size=2 (checkcast Integer) 0: aload_1 (invokevirtual ^int Integer/intValue []) 1: checkcast #25; //class java/lang/I (istore_2) 4: invokevirtual #29; //Method java/lang/ (iconst_1) 7: istore_2 (istore_3) 8: iconst_1 :loop 9: istore_3 (iload_2) 10: iload_2 (ifeq :end) 11: ifeq 24 (ilaod_2) 14: iload_2 (iload_3) 15: iload_3 (imul) 16: imul (istore_3) 17: istore_3 (iinc 2 -1) 18: iinc 2, -1 (goto :loop) 21: goto 10 :end 24: iload_3 (iload_3) 25: invokestatic #33; //Method java/lang/ (invokestatic ^Integer Integer/valueOf [int]) 28: areturn (areturn)))
  • 42. syntactic-closure http://d.hatena.ne.jp/athos/20120506/syntactic_closure_in_clojure • syntactic closuresによる健全なマクロを定義で きるようにするライブラリ 低レベル 高レベル • syntax-quoteで定義できない 不 健 全 • 伝統的なマクロ ある種のマクロが定義可能に • syntactic closures (define-syntax or [expr1 expr2] 健 • explicit renaming • syntax-rules 全 • syntax-case (sc-macro-transformer (fn [env] (quasiquote (let [val ~(make-syntactic-closure env nil expr1)] (if val val ~(make-syntactic-closure env nil expr2))))))) (let [val true] (let [val true] (or false val)) (let [val396 false] (if val396 val396 val))
  • 43.  まとめ • Clojureのマクロ周りには遊べるおも ちゃがたくさん • アイデア次第で貢献できる可能性? • nagoya-lispに参加しましょう