SlideShare a Scribd company logo
1 of 38
Download to read offline
まっくろわーるど
じゅりあらんぐッ!
yomichi
JuliaTokyo #3 2015/04/25
スライドとサンプルコード
https://github.com/yomichi/JuliaTokyo3
1 / 38
自己紹介
HN : 夜道, yomichi
twitter : @yomichi_137
ぽすどくにねんせい
統計物理学・計算物理学
主にモンテカルロ法とか
言語は C++, Python, Julia
イベント(勉強会)実況勢
最近だと全ゲ連(同人ゲーム開発)とか、
PyConJP (Python) とか、JuliaTokyo とか
Julia nightly build 勢
Julia の開発環境は REPL と Vim
コミケで Julia 本出したりしてます
blog とか締め切りがないので書けません><
抽選受かっていたら次の夏にも出します
多分今回の話をもう少し詳しく書きます
(thanks @am_11)
2 / 38
今日のお話
1 Symbol 型と Expr 型 – Julia の抽象構文木
2 マクロシステム
3 メタプログラミング – どう使うか
メタプログラミングとかマクロ展開とかのお話です
(Julia の中では) 難しそう or 難しいためか余り触れられてこな
い話
確実に 30 分では終わらないので適当に飛ばします
一応スライドだけでも読めるつもりで作った 1
ので、興味ある方
はあとでゆっくりとどうぞ
いつものことですが公式ドキュメントが一番詳しくてわかりやす
く、ほぼ常に最新なので、英語が苦じゃない人はそちらがおす
すめ
未確認で進行形ネタを仕込もうかと思ったけれどそんな余裕が
ありませんでした
なのでタイトルは出オチです
1
だから詰め込みすぎになった、とも言う
3 / 38
Outline
1 Symbol 型と Expr 型 – Julia の抽象構文木
2 マクロシステム
3 メタプログラミング – どう使うか
4 / 38
Julia の抽象構文木 (AST)
例えば x + (y + z) という式は Julia
の中の人からは右図のように木構造
(抽象構文木)として見えている
:call は関数呼び出しの意味
+ は中置が認められているというだ
けで普通の関数であることに注意
つまり正確には +(x, +(y, z))
Julia は式をこのように抽象構文木に変
換して、それから式の評価をしている
この構造をそのまま保持することで、
式やプログラムそのものをデータと
して扱える(=同図像性)
プログラムを生成するプログラムも
書ける(=メタプログラミング)
:call
:call:+
:+
:x
:y :z
5 / 38
Julia の抽象構文木 (AST) と Symbol 型、 Expr 型
Julia における最も重要な型(データ構造)のうち 2 つが
Symbol と Expr である
Symbol は識別子・変数名を表す型
Expr は Julia そのものの抽象構文木(AST)を表す型
これらの型のオブジェクト(シンボル、AST)は:() や
quote ... end を用いることで作ることができる
1 julia > s = :x
2 :x
3
4 julia > typeof(s)
5 Symbol
6
7 julia > ex = :(x + 1)
8 :(x + 1)
9
10 julia > typeof(ex)
11 Expr
6 / 38
Julia の抽象構文木 (AST) と Symbol 型、 Expr 型
Expr は head, args, typ の 3 つの field を持つ
1 head は行う操作
2 args は操作の対象(引数)
3 typ は結果の型(確定していれば)
ほとんどの場合で Any であり、気にする必要はほとんど無い
Base.dump でまとめて表示できる
Base.Meta.show_sexpr を使うと S 式で表示できる
1 julia > dump(ex)
2 Expr
3 head: Symbol call
4 args: Array(Any ,(3 ,))
5 1: Symbol +
6 2: Symbol x
7 3: Int64 1
8 typ: Any
9
10 julia > Base.Meta.show_sexpr(ex)
11 (:call , :+, :x, 1)
7 / 38
Julia の抽象構文木 (AST) と Symbol 型、 Expr 型
AST は木構造なので節と葉を持つ
節は Expr 型
葉は Symbol 型の値(変数名)かリテラル(数値型・文字列型)
今回、簡単のため Expr, Symbol, リテラルをすべてまとめて
AST と呼ぶ
1 julia > dump( :( x + ( y + z ) ) )
2 Expr
3 head: Symbol call
4 args: Array(Any ,(3 ,))
5 1: Symbol +
6 2: Symbol x
7 3: Expr
8 head: Symbol call
9 args: Array(Any ,(3 ,))
10 1: Symbol +
11 2: Symbol y
12 3: Symbol z
13 typ: Any
14 typ: Any
8 / 38
変数補間 (interpolation)
quote で AST を作るときに、$ を使うことで変数や式の値を
入れることができる
文字列 (" ") やプロセス (‘ ‘) における補間と同じ
1 julia > y = 42
2 42
3
4 julia > :(x = y)
5 :(x = y)
6
7 julia > :(x = $y)
8 :(x = 42)
9
10 julia > :(x = sin (1.0))
11 :(x = sin (1.0))
12
13 julia > :(x = $(sin (1.0)))
14 :(x = 0.8414709848078965)
9 / 38
変数補間で Symbol を陽に残す
例えば Symbol を受け取る関数を呼び出す式を quote したいと
きに、その Symbol を変数補間で与えたい
この時そのまま$s と書くと、Symbol ではなく名前が書き込ま
れてしまう
ほとんどのマクロではこの挙動の方が都合がいい
配列かタプルに隠して埋め込み、後から取り出せばよい
1 julia > :( foo(:a) ) # こ れ が 欲 し い
2 :(foo(:a))
3
4 julia > s = :a ;
5 julia > :( foo($s) ) # 直 接 埋 め 込 む と ダ メ
6 :(foo(a))
7
8 julia > :( foo( $[s]...) ) # 一 度 配 列 に 隠 す
9 :(foo ([:a]...))
10
11 julia > :( foo( $(s ,)...) ) # タ プ ル で も 良 い
12 :(foo ((:a ,)...))
10 / 38
式の評価
eval 関数に AST を渡すことで、AST の評価を行える
AST に未定義な変数を含めることができるが、定義する前に
AST を評価するともちろんエラーが出る
1 julia > x
2 ERROR: UndefVarError : x not defined
3
4 julia > ex = :(2 * x)
5 :(2x)
6
7 julia > eval(ex)
8 ERROR: UndefVarError : x not defined
9
10 julia > x = 42
11 42
12
13 julia > eval(ex)
14 84
11 / 38
式の操作
Expr は immutable ではないので、AST を操作することがで
きる
1 julia > ex
2 :(2x)
3
4 julia > x, eval(ex)
5 (42 ,84)
6
7 julia > ex.args [2] = 20;
8
9 julia > ex
10 :(20x)
11
12 julia > x, eval(ex)
13 (42 ,840)
12 / 38
第一級オブジェクトとしての AST
– 同図像性 (Homoiconic)
ソースコードを quote することで AST を生み出すことがで
きた
Expr のコンストラクタを呼び出して作ることもできる
parse 関数を使うことで、文字列から作ることもできる
1 julia > parse("x+1")
2 :(x + 1)
もちろん関数に渡したり関数から受け取ったりできる
既に eval や dump、parse といった実例を見てきた
AST を渡すと別の AST に変換する関数を作ることもできる
eval に渡すことでいつでも AST を評価・実行できる
このように、自分自身の AST そのものをデータとして扱える
言語の性質を homoiconic と呼ぶ
AST(プログラム)を自動生成するプログラムを簡単に書ける
– メタプログラミング
マクロを使うことで、より自然な構文の書き換えを行うことが
できる
13 / 38
Outline
1 Symbol 型と Expr 型 – Julia の抽象構文木
2 マクロシステム
3 メタプログラミング – どう使うか
14 / 38
マクロ
マクロは macro キーワードで定義して、@name という形で呼
び出す
マクロがやること
1 引数をそれぞれ:() で quote して
2 普通の関数と同様に何か仕事して
3 返ってきた値を eval する
AST を受け取って AST を返す関数の場合、いちいち quote
や eval をする必要があった
eval( foo( :( x+1 ) ) )
マクロでは @foo(x+1) と書ける
@foo x+1 のようにも書ける
マクロは関数と違って健全であるという特徴もある
説明は次頁
15 / 38
変数捕捉と健全な (hygienic) マクロ
マクロは AST を変換(マクロ展開)して、新しい AST を呼び
出し元に貼り付ける
展開された AST に含まれる名前が、呼び出し元の文脈にある
ものと衝突する事がある(=変数捕捉)
1 必要な名前が呼び出し元で別の値に束縛されている事がある
2 呼び出し元の変数を再束縛してしまう
名前の付け方に細工をすることで回避する
1 マクロが定義されているモジュール名を使って名前を修飾する
2 変数に値を代入するときは、重複しない(今まで作られていな
くて、これからも作られない)名前を生成して変数名とする
Base.gensym で生成可能
Julia のマクロ展開では全て自動でやってくれる(健全なマ
クロ)
16 / 38
変数捕捉と健全なマクロ
Base.macroexpand を使うとマクロ展開した結果を得ること
ができる
関数なので quote が必要
1 module JT3 # 以 下 全 て の マ ク ロ は こ の モ ジ ュ ー
ル 内 に あ る
2 macro setx_A ()
3 :( x = sin (1.0) )
4 end
5 end
1 julia > macroexpand( :( JT3.@setx_A ) )
2 :(#30#x = JT3.sin (1.0))
1 sin を JT3 で修飾することで、呼び出し元が sin を隠蔽して
いるかどうかを気にしなくてよくなる
JT3.sin は(名前の隠蔽をしていなければ)Base.sin になる
2 #30#x という名前を作ることで、呼び出し元に x があるかど
うかを気にしなくてよくなる
17 / 38
変数捕捉と健全なマクロ
1 macro setx_A ()
2 :( x = sin (1.0) )
3 end
Julia が自動的に x を保護してくれるために、残念ながらこの
マクロを使っても呼び出し元の x に変化はおきない
1 julia > x
2 ERROR: UndefVarError : x not defined
3
4 julia > JT3.@setx_A
5 0.8414709848078965
6
7 julia > x
8 ERROR: UndefVarError : x not defined
呼び出し元に影響をあたえるためには、名前の保護を無効化す
ることで意図的に変数捕捉を起こす必要がある (Base.esc)
18 / 38
意図的な変数捕捉
Symbol や Expr に Base.esc を作用させると、それらに含ま
れる名前は保護されなくなる
@setx_B のようにまとめてエスケープしてもよいし
@setx_C のように個別にエスケープしてもよい
Base.esc が引数にとれるのは Symbol か Expr だけなので:x
と quote が必要
esc(:x) の結果を埋め込むために$() が必要
1 macro setx_B ()
2 esc( :( x = sin (1.0)) )
3 end
4 macro setx_C ()
5 :( $(esc(:x)) = sin (1.0) )
6 end
1 julia > macroexpand (:( JT3.@setx_B ) )
2 :(x = sin (1.0))
3
4 julia > macroexpand (:( JT3.@setx_C ) )
5 :(x = JT3.sin (1.0))
19 / 38
意図的な変数捕捉
このマクロを使うと x の値を変えることができる
1 julia > x
2 ERROR: UndefVarError : x not defined
3
4 julia > JT3.@setx_B
5 0.8414709848078965
6
7 julia > x
8 0.8414709848078965
9
10 julia > x = 0;
11
12 julia > JT3.@setx_C
13 0.8414709848078965
14
15 julia > x
16 0.8414709848078965
20 / 38
潔癖症レベルで健全
マクロ引数に含まれている変数名も全て保護される
つまり呼び出し元とは関係ないものとなる
まず確実に esc が必要
Symbol のまま残したいときはエスケープしなくても良い
ぶっちゃけ迷惑
1 macro setf_A(ex , val)
2 :( $ex = $val )
3 end
1 julia > macroexpand (:( JT3.@setf_A x y) )
2 :(#8#x = JT3.y)
3
4 julia > x, y = 0, 42;
5
6 julia > JT3.@setf_A x y
7 ERROR: UndefVarError : y not defined
21 / 38
回避例
基本的にやることはさっきと同じ
今回の@setf_C のように、あらかじめ外でエスケープしてか
ら quote 文に注入することもできる
自分の好みで、見やすいものを使ってください
1 macro setf_B(ex , val)
2 esc (:( $ex = $val ))
3 end
4
5 macro setf_C(ex , val)
6 esc_ex = esc(ex)
7 esc_val = esc(val)
8 :( $esc_ex = $esc_val)
9 end
1 julia > macroexpand (:( JT3.@setf_B x y))
2 :(x = y)
22 / 38
近未来
この「健全すぎる」という件は Julia-0.4 のリリースまでには
修正される予定
マクロに渡された式中の名前が保護されなくなる
(あまりないと思うけれど)保護したくなったら自分で gensym
やモジュール名修飾すること
Base.@hygienic に関数定義を食わせるとその関数でも名前保
護が行われる
Issue #6910, #10940
2015-04-25 現在では merge されていないので注意
moon/hygienic-macros branch をビルドすれば試せる
1 macro setf_A(ex , val)
2 :( $ex = $val )
3 end
1 julia -future > macroexpand (:( JT3.@setf_A x y
))
2 :(x = y)
23 / 38
近未来
もちろん直に書いた名前は今までどおり保護されることとなる
Symbol は$:x とすることでお手軽にエスケープできる
1 macro setx_A ()
2 :( x = sin (1.0) )
3 end
4 macro setx_D ()
5 :( $:x = sin (1.0) )
6 end
1 julia -future > macroexpand (:( JT3.@setx_A ))
2 :(#3#x = JT3.sin (1.0))
3 julia -future > macroexpand (:( JT3.@setx_D ))
4 :(x = JT3.sin (1.0))
24 / 38
近未来
従来の Base.esc も当然使えるけれど、バグっている?
改めて議論の流れを確認してから報告します
1 macro setx_B ()
2 esc( :( x = sin (1.0)) )
3 end
4
5 macro setx_C ()
6 :( $(esc(:x)) = sin (1.0) )
7 end
1 julia -future > macroexpand (:( JT3.@setx_B ))
2 :(#4#x = JT3.sin (1.0))
3
4 julia -future > macroexpand (:( JT3.@setx_B ))
5 :(x = JT3.sin (1.0))
25 / 38
Outline
1 Symbol 型と Expr 型 – Julia の抽象構文木
2 マクロシステム
3 メタプログラミング – どう使うか
26 / 38
マクロの効用 – 評価タイミングの制御
マクロ呼出しでは式を式のまま、値に評価せずに渡すので、評
価タイミングを自分で制御できる
評価しなかったり、複数回評価したりも可能
与えた式の実行にかかる時間を計測する@time では、現在時刻
を調べる操作を前後にやる必要がある
Expr や無名関数にくるむことで関数でもほぼ同じことができ
るが、呼び出し側がいちいちそれをやるのは面倒臭すぎる
1 macro time(ex)
2 quote
3 t0 = time_ns ()
4 val = $(esc(ex))
5 t1 = time_ns ()
6 println (1.e-9(t1 -t0), "␣sec")
7 val
8 end
9 end
27 / 38
マクロの効用 – コンパイル時計算
マクロ展開は式のパース及び関数の JIT コンパイル時に行われ
て、構文そのものが書き換わる
そのため、定数などをコンパイル時に計算をおこなうことで実
行時間を短くすることができうる
1 function isnotcomment(line)
2 !ismatch(r"^s*(#|$)", line)
3 end
4 function isnotcomment_nomacro (line)
5 !ismatch(Regex("^s*(#|$)"), line)
6 end
文字列リテラルの直前に文字を置くと、自動的にマクロ呼出し
になる
@r_str は正規表現を作るマクロ
1 julia > foo"hoge"
2 ERROR: UndefVarError : @foo_str not defined
28 / 38
マクロの効用 – コンパイル時計算
マクロを使わないと毎回正規表現を作ることになる
code_llvm 関数を使って LLVM コードにコンパイルすると、
非マクロ版の方が明らかに中身が多いことが分かる
マクロ版
1 julia > code_llvm(JT3.isnotcomment , (
ASCIIString ,))
2
3 define i1 @julia_isnotcomment_44329 (%
jl_value_t *) {
4 top:
5 %1 = call i1 @julia_ismatch4396 (%
jl_value_t* inttoptr (i64 4591287408 to
%jl_value_t *), %jl_value_t* %0, i64 0)
6 %2 = xor i1 %1, true
7 ret i1 %2
8 }
29 / 38
マクロの効用 – コンパイル時計算
非マクロ版
1 julia > code_llvm(JT3.isnotcomment_nomacro , (
ASCIIString ,))
2
3 define i1 @julia_isnotcomment_nomacro_44330
(% jl_value_t *) {
4 top:
5 %1 = alloca [3 x %jl_value_t *], align 8
6 %.sub = getelementptr inbounds [3 x %
jl_value_t *]* %1, i64 0, i64 0
7 %2 = getelementptr [3 x %jl_value_t *]* %1,
i64 0, i64 2
8 store %jl_value_t* inttoptr (i64 2 to %
jl_value_t *), %jl_value_t ** %.sub ,
align 8
9 %3 = load %jl_value_t *** @jl_pgcstack ,
align 8
10 %4 = getelementptr [3 x %jl_value_t *]* %1,
i64 0, i64 1
11 %.c = bitcast %jl_value_t ** %3 to %
jl_value_t*
12 store %jl_value_t* %.c, %jl_value_t ** %4,
align 8
13 store %jl_value_t ** %.sub , %jl_value_t ***
@jl_pgcstack , align 8
14 store %jl_value_t* null , %jl_value_t ** %2,
align 8
15 %5 = load %jl_value_t ** inttoptr (i64
4580071440 to %jl_value_t **), align 16
16 %6 = load %jl_value_t ** inttoptr (i64
4588059808 to %jl_value_t **), align 32
17 %7 = bitcast %jl_value_t* %6 to i32*
18 %8 = load i32* %7, align 8
19 %9 = call %jl_value_t* @julia_call1392 (%
jl_value_t* %5, %jl_value_t* inttoptr (
i64 4600855376 to %jl_value_t *), i32
%8)
20 store %jl_value_t* %9, %jl_value_t ** %2,
align 8
21 %10 = call i1 @julia_ismatch4396 (%
jl_value_t* %9, %jl_value_t* %0, i64 0)
22 %11 = xor i1 %10, true
23 %12 = load %jl_value_t ** %4, align 8
24 %13 = getelementptr inbounds %jl_value_t*
%12, i64 0, i32 0
25 store %jl_value_t ** %13, %jl_value_t ***
@jl_pgcstack , align 8
26 ret i1 %11
27 }
30 / 38
Generated function
4/21 に新しく Base.@generated が導入された
ドキュメントも同時に追加された
これまでに渡されたことのない型の組み合わせの時は、関数本
体を実行する
その時、引数の値は参照できず、自動的に型が得られる
同じ型の組み合わせを再度投げると、本体は実行されず返り値
のみが得られる
AST を返すようにすることで、マクロのように使うことがで
きる
マクロと違い型による多重ディスパッチが働くことが利点
関数本体の処理内容によっては、2 回目以降も実行されること
があるらしい
引数の型別にコンパイル時計算が可能
パラメタライズ型の型パラメータに整数などを渡せて、違う整
数では違う型になることを利用すると、数値ごとにコンパイル
時計算しておくことができる
31 / 38
Generated function
百聞は一見にしかず
Int を 2 回目以降渡した時には println(x) が実行されない
こと、
println(x) で値ではなく型が出力されていることに注目
1 @generated function gen_fn(x)
2 println(x)
3 :(x*x)
4 end
1 julia > JT3.gen_fn (3)
2 Int64
3 9
4
5 julia > JT3.gen_fn (3)
6 9
7
8 julia > JT3.gen_fn (5)
9 25
10
11 julia > JT3.gen_fn (3.14)
12 Float64
13 9.8596
32 / 38
Generated function – コンパイル時フィボナッチ
generated function では再計算しないので、再帰でやっても十
分速い
1 type IntTag{N} end
2
3 @generated function fib{N}(:: IntTag{N})
4 N < 3 && return 1
5 ret = fib(N-1) + fib(N-2)
6 :( $ret)
7 end
8
9 fib(N:: Integer) = fib(IntTag{N}())
1 julia > @time JT3.fib (500)
2 elapsed time: 0.714843811 seconds (13 MB
allocated)
3 4859788740867454402
4 # 実 は オ ー バ ー フ ロ ー し て い る ( ぉ
5
6 julia > @time JT3.fib (500)
7 elapsed time: 1.2101e-5 seconds (192 bytes
allocated)
8 4859788740867454402
33 / 38
Generated function – コンパイル時フィボナッチ
再計算していないことは @show ret とかやるとよくわかる
あくまでデモ用なので、フィボナッチ数列を作りたい場合は配
列を用意してループを回したほうがよい
BigNum などが使えないのでオーバーフローなどに注意
再帰が深くなるとスタックオーバーフローする
1 @generated function fib{N}(:: IntTag{N})
2 N < 3 && return 1
3 ret = fib(N-1) + fib(N-2)
4 @show N, ret
5 :( $ret)
1 julia > JT3.fib (100);
2 (N,ret) = (3,2)
3 (N,ret) = (4,3)
4 (N,ret) = (5,5)
5 (N,ret) = (6,8)
6 # 中 略
7 (N,ret) = (98 ,6174643828739884737)
8 (N,ret) = (99 , -2437933049959450366) # Oops
9 (N,ret) = (100 ,3736710778780434371)
34 / 38
メタプログラミングのやり方
最終的に評価したい式(出力)と、使える名前や式(入力)を、
具体的に書いて並べてみる
入力をどう組み立て・変形すれば出力の式になるのかを考える
今回説明した、変数補間や名前保護のルールが身につけば、あ
る程度のマクロやメタプログラミングは少しの慣れで書ける
はず
macroexpand を使って確認するのが良い
REPL など、Main モジュールでテストをすると、自動でなされ
るモジュール名修飾の結果がわかりづらくなるので、できるだ
け別のモジュールの中で書いたほうが良い
35 / 38
関数定義
関数定義も AST で表せるので、関数の自動生成なんてことも
できる
形がほとんど同じで、部品(使う関数など)の名前だけが違う
関数群などでは是非
1 type MyFloat
2 val :: Float64
3 end
4 for fn in (:sin , :cos , :tan)
5 eval(Expr (:import , :Base , fn))
6 @eval ($fn)(mf:: MyFloat) = ($fn)(mf.
val)
7 end
36 / 38
関数定義をジャックするマクロ
関数定義を自動的に別の関数定義に置き換えるマクロを作るこ
ともできる
自動ロギング、メモ化、末尾再帰最適化などなど
一度に展開形にするのはまず無理
受け取った Expr 型のオブジェクトから関数名や引数名などを
抽出する必要がある
いっそオブジェクトの追記・書き換えで完成させるのもアリ
渡された関数定義を、名前を変えて実行してしまい、新しく作
る関数の中から呼ぶのも有効
この場合でも「最後にはこう展開されて欲しい」という対応関
係を最初に考えるのが大事
メモ化や末尾再帰最適化など、そもそもどうやって実現するの
かを考えるところから始まる
基本的には macroexpand で結果を確認したり、dump, @show
で中身を見ながら試行錯誤
成果物が役立つかは別としても、かなり勉強・練習になる
サンプルとしてメモ化マクロを作ってみたので興味があれば
ちなみに Memoize.jl なんていうパッケージも既に存在する 37 / 38
まとめ
Julia の構文を Julia の中からいじる方法(メタプログラミン
グ)を見てきた
コードを自動生成することで全体のコード量や実装時間を減ら
せる
マクロや@generated でコンパイル時計算をしたり
Memoize.jl などで関数を自動メモ化したりすることで実行性
能をあげられる(かもしれない)
自分で書く場合、どういう結果が出て欲しいかをまず考える
macroexpand, dump, @show あたりを駆使して試行錯誤
参考資料
Julia 公式 Document
英語が読めるならこれを読みながら手を動かせばよい
On Lisp, (著: Paul Graham, 和訳:野田開)
Lisp 系の言語を学ぶと Julia が多大な影響を受けていることがよ
くわかる
マクロだけじゃなくてクロージャなどの理解にも役立つ
38 / 38

More Related Content

What's hot

これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールNobuhisa Koizumi
 
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020Fujio Kojima
 
Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Prunus 1350
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターsohta
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~Fujio Kojima
 
メタプログラミング C#
メタプログラミング C#メタプログラミング C#
メタプログラミング C#Fujio Kojima
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話infinite_loop
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPIDaisuke Igarashi
 
葉物野菜を見極めたい!by Keras
葉物野菜を見極めたい!by Keras葉物野菜を見極めたい!by Keras
葉物野菜を見極めたい!by KerasYuji Kawakami
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門SatoYu1ro
 
すごいH 第12章モノイド
すごいH 第12章モノイドすごいH 第12章モノイド
すごいH 第12章モノイドShinta Hatatani
 
モナドがいっぱい!
モナドがいっぱい!モナドがいっぱい!
モナドがいっぱい!Kenta Sato
 
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」fukuoka.ex
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門kwatch
 
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」fukuoka.ex
 
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要Toshihiro Kamishima
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~Fujio Kojima
 

What's hot (20)

これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツール
 
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
 
Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
 
メタプログラミング C#
メタプログラミング C#メタプログラミング C#
メタプログラミング C#
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話
 
Boost Tour 1.50.0 All
Boost Tour 1.50.0 AllBoost Tour 1.50.0 All
Boost Tour 1.50.0 All
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
 
葉物野菜を見極めたい!by Keras
葉物野菜を見極めたい!by Keras葉物野菜を見極めたい!by Keras
葉物野菜を見極めたい!by Keras
 
講座Java入門
講座Java入門講座Java入門
講座Java入門
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門
 
すごいH 第12章モノイド
すごいH 第12章モノイドすごいH 第12章モノイド
すごいH 第12章モノイド
 
モナドがいっぱい!
モナドがいっぱい!モナドがいっぱい!
モナドがいっぱい!
 
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
 
boost tour 1.48.0 all
boost tour 1.48.0 allboost tour 1.48.0 all
boost tour 1.48.0 all
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
 
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~
 

Viewers also liked

Julia最新情報 2015
Julia最新情報 2015Julia最新情報 2015
Julia最新情報 2015Kenta Sato
 
Plotly Julia API
Plotly Julia APIPlotly Julia API
Plotly Julia APIE2D3.org
 
Juliaのススメ
JuliaのススメJuliaのススメ
JuliaのススメAi Makabi
 
Julia 100 exercises #JuliaTokyo
Julia 100 exercises #JuliaTokyoJulia 100 exercises #JuliaTokyo
Julia 100 exercises #JuliaTokyoAki Ariga
 
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)Kenta Sato
 
Juliaのパッケージをつくろう!
Juliaのパッケージをつくろう!Juliaのパッケージをつくろう!
Juliaのパッケージをつくろう!Kenta Sato
 
メカ女子将棋Julia tokyo#1
メカ女子将棋Julia tokyo#1メカ女子将棋Julia tokyo#1
メカ女子将棋Julia tokyo#1Takeshi Kimura
 
Julia0.3でランダムフォレスト
Julia0.3でランダムフォレストJulia0.3でランダムフォレスト
Julia0.3でランダムフォレストAtsushi Hayakawa
 
プログラミング言語 Julia の紹介
プログラミング言語 Julia の紹介プログラミング言語 Julia の紹介
プログラミング言語 Julia の紹介Kentaro Iizuka
 

Viewers also liked (10)

Julia最新情報 2015
Julia最新情報 2015Julia最新情報 2015
Julia最新情報 2015
 
Plotly Julia API
Plotly Julia APIPlotly Julia API
Plotly Julia API
 
Juliaのススメ
JuliaのススメJuliaのススメ
Juliaのススメ
 
Julia 100 exercises #JuliaTokyo
Julia 100 exercises #JuliaTokyoJulia 100 exercises #JuliaTokyo
Julia 100 exercises #JuliaTokyo
 
Julia入門
Julia入門Julia入門
Julia入門
 
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)
Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)
 
Juliaのパッケージをつくろう!
Juliaのパッケージをつくろう!Juliaのパッケージをつくろう!
Juliaのパッケージをつくろう!
 
メカ女子将棋Julia tokyo#1
メカ女子将棋Julia tokyo#1メカ女子将棋Julia tokyo#1
メカ女子将棋Julia tokyo#1
 
Julia0.3でランダムフォレスト
Julia0.3でランダムフォレストJulia0.3でランダムフォレスト
Julia0.3でランダムフォレスト
 
プログラミング言語 Julia の紹介
プログラミング言語 Julia の紹介プログラミング言語 Julia の紹介
プログラミング言語 Julia の紹介
 

Similar to Metaprogramming in JuliaLang

Scalamacrosについて
ScalamacrosについてScalamacrosについて
Scalamacrosについてdekosuke
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!bitter_fox
 
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」Nagi Teramo
 
Nds meetup8 lt
Nds meetup8 ltNds meetup8 lt
Nds meetup8 ltushiboy
 
ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)taskie
 
appengine ja night #4 Transaction Puzzlers
appengine ja night #4 Transaction Puzzlersappengine ja night #4 Transaction Puzzlers
appengine ja night #4 Transaction PuzzlersSuguru ARAKAWA
 
初めてのHaskell (表)
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)karky7
 
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門Teng Tokoro
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8y_taka_23
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Ransui Iso
 
言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3Kenta Hattori
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 
scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)Ryuichi ITO
 

Similar to Metaprogramming in JuliaLang (20)

Scalamacrosについて
ScalamacrosについてScalamacrosについて
Scalamacrosについて
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
 
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
Nds meetup8 lt
Nds meetup8 ltNds meetup8 lt
Nds meetup8 lt
 
ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)
 
appengine ja night #4 Transaction Puzzlers
appengine ja night #4 Transaction Puzzlersappengine ja night #4 Transaction Puzzlers
appengine ja night #4 Transaction Puzzlers
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
初めてのHaskell (表)
初めてのHaskell (表)初めてのHaskell (表)
初めてのHaskell (表)
 
ALPSチュートリアル(6) Matplotlib入門
ALPSチュートリアル(6) Matplotlib入門ALPSチュートリアル(6) Matplotlib入門
ALPSチュートリアル(6) Matplotlib入門
 
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門
マイクロマウスのための MATLAB/Simulink 講座 第1回 - MATLAB入門
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
 
言語処理系入門3
言語処理系入門3言語処理系入門3
言語処理系入門3
 
Haskell
HaskellHaskell
Haskell
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)
 

Recently uploaded

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 

Recently uploaded (10)

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 

Metaprogramming in JuliaLang

  • 2. 自己紹介 HN : 夜道, yomichi twitter : @yomichi_137 ぽすどくにねんせい 統計物理学・計算物理学 主にモンテカルロ法とか 言語は C++, Python, Julia イベント(勉強会)実況勢 最近だと全ゲ連(同人ゲーム開発)とか、 PyConJP (Python) とか、JuliaTokyo とか Julia nightly build 勢 Julia の開発環境は REPL と Vim コミケで Julia 本出したりしてます blog とか締め切りがないので書けません>< 抽選受かっていたら次の夏にも出します 多分今回の話をもう少し詳しく書きます (thanks @am_11) 2 / 38
  • 3. 今日のお話 1 Symbol 型と Expr 型 – Julia の抽象構文木 2 マクロシステム 3 メタプログラミング – どう使うか メタプログラミングとかマクロ展開とかのお話です (Julia の中では) 難しそう or 難しいためか余り触れられてこな い話 確実に 30 分では終わらないので適当に飛ばします 一応スライドだけでも読めるつもりで作った 1 ので、興味ある方 はあとでゆっくりとどうぞ いつものことですが公式ドキュメントが一番詳しくてわかりやす く、ほぼ常に最新なので、英語が苦じゃない人はそちらがおす すめ 未確認で進行形ネタを仕込もうかと思ったけれどそんな余裕が ありませんでした なのでタイトルは出オチです 1 だから詰め込みすぎになった、とも言う 3 / 38
  • 4. Outline 1 Symbol 型と Expr 型 – Julia の抽象構文木 2 マクロシステム 3 メタプログラミング – どう使うか 4 / 38
  • 5. Julia の抽象構文木 (AST) 例えば x + (y + z) という式は Julia の中の人からは右図のように木構造 (抽象構文木)として見えている :call は関数呼び出しの意味 + は中置が認められているというだ けで普通の関数であることに注意 つまり正確には +(x, +(y, z)) Julia は式をこのように抽象構文木に変 換して、それから式の評価をしている この構造をそのまま保持することで、 式やプログラムそのものをデータと して扱える(=同図像性) プログラムを生成するプログラムも 書ける(=メタプログラミング) :call :call:+ :+ :x :y :z 5 / 38
  • 6. Julia の抽象構文木 (AST) と Symbol 型、 Expr 型 Julia における最も重要な型(データ構造)のうち 2 つが Symbol と Expr である Symbol は識別子・変数名を表す型 Expr は Julia そのものの抽象構文木(AST)を表す型 これらの型のオブジェクト(シンボル、AST)は:() や quote ... end を用いることで作ることができる 1 julia > s = :x 2 :x 3 4 julia > typeof(s) 5 Symbol 6 7 julia > ex = :(x + 1) 8 :(x + 1) 9 10 julia > typeof(ex) 11 Expr 6 / 38
  • 7. Julia の抽象構文木 (AST) と Symbol 型、 Expr 型 Expr は head, args, typ の 3 つの field を持つ 1 head は行う操作 2 args は操作の対象(引数) 3 typ は結果の型(確定していれば) ほとんどの場合で Any であり、気にする必要はほとんど無い Base.dump でまとめて表示できる Base.Meta.show_sexpr を使うと S 式で表示できる 1 julia > dump(ex) 2 Expr 3 head: Symbol call 4 args: Array(Any ,(3 ,)) 5 1: Symbol + 6 2: Symbol x 7 3: Int64 1 8 typ: Any 9 10 julia > Base.Meta.show_sexpr(ex) 11 (:call , :+, :x, 1) 7 / 38
  • 8. Julia の抽象構文木 (AST) と Symbol 型、 Expr 型 AST は木構造なので節と葉を持つ 節は Expr 型 葉は Symbol 型の値(変数名)かリテラル(数値型・文字列型) 今回、簡単のため Expr, Symbol, リテラルをすべてまとめて AST と呼ぶ 1 julia > dump( :( x + ( y + z ) ) ) 2 Expr 3 head: Symbol call 4 args: Array(Any ,(3 ,)) 5 1: Symbol + 6 2: Symbol x 7 3: Expr 8 head: Symbol call 9 args: Array(Any ,(3 ,)) 10 1: Symbol + 11 2: Symbol y 12 3: Symbol z 13 typ: Any 14 typ: Any 8 / 38
  • 9. 変数補間 (interpolation) quote で AST を作るときに、$ を使うことで変数や式の値を 入れることができる 文字列 (" ") やプロセス (‘ ‘) における補間と同じ 1 julia > y = 42 2 42 3 4 julia > :(x = y) 5 :(x = y) 6 7 julia > :(x = $y) 8 :(x = 42) 9 10 julia > :(x = sin (1.0)) 11 :(x = sin (1.0)) 12 13 julia > :(x = $(sin (1.0))) 14 :(x = 0.8414709848078965) 9 / 38
  • 10. 変数補間で Symbol を陽に残す 例えば Symbol を受け取る関数を呼び出す式を quote したいと きに、その Symbol を変数補間で与えたい この時そのまま$s と書くと、Symbol ではなく名前が書き込ま れてしまう ほとんどのマクロではこの挙動の方が都合がいい 配列かタプルに隠して埋め込み、後から取り出せばよい 1 julia > :( foo(:a) ) # こ れ が 欲 し い 2 :(foo(:a)) 3 4 julia > s = :a ; 5 julia > :( foo($s) ) # 直 接 埋 め 込 む と ダ メ 6 :(foo(a)) 7 8 julia > :( foo( $[s]...) ) # 一 度 配 列 に 隠 す 9 :(foo ([:a]...)) 10 11 julia > :( foo( $(s ,)...) ) # タ プ ル で も 良 い 12 :(foo ((:a ,)...)) 10 / 38
  • 11. 式の評価 eval 関数に AST を渡すことで、AST の評価を行える AST に未定義な変数を含めることができるが、定義する前に AST を評価するともちろんエラーが出る 1 julia > x 2 ERROR: UndefVarError : x not defined 3 4 julia > ex = :(2 * x) 5 :(2x) 6 7 julia > eval(ex) 8 ERROR: UndefVarError : x not defined 9 10 julia > x = 42 11 42 12 13 julia > eval(ex) 14 84 11 / 38
  • 12. 式の操作 Expr は immutable ではないので、AST を操作することがで きる 1 julia > ex 2 :(2x) 3 4 julia > x, eval(ex) 5 (42 ,84) 6 7 julia > ex.args [2] = 20; 8 9 julia > ex 10 :(20x) 11 12 julia > x, eval(ex) 13 (42 ,840) 12 / 38
  • 13. 第一級オブジェクトとしての AST – 同図像性 (Homoiconic) ソースコードを quote することで AST を生み出すことがで きた Expr のコンストラクタを呼び出して作ることもできる parse 関数を使うことで、文字列から作ることもできる 1 julia > parse("x+1") 2 :(x + 1) もちろん関数に渡したり関数から受け取ったりできる 既に eval や dump、parse といった実例を見てきた AST を渡すと別の AST に変換する関数を作ることもできる eval に渡すことでいつでも AST を評価・実行できる このように、自分自身の AST そのものをデータとして扱える 言語の性質を homoiconic と呼ぶ AST(プログラム)を自動生成するプログラムを簡単に書ける – メタプログラミング マクロを使うことで、より自然な構文の書き換えを行うことが できる 13 / 38
  • 14. Outline 1 Symbol 型と Expr 型 – Julia の抽象構文木 2 マクロシステム 3 メタプログラミング – どう使うか 14 / 38
  • 15. マクロ マクロは macro キーワードで定義して、@name という形で呼 び出す マクロがやること 1 引数をそれぞれ:() で quote して 2 普通の関数と同様に何か仕事して 3 返ってきた値を eval する AST を受け取って AST を返す関数の場合、いちいち quote や eval をする必要があった eval( foo( :( x+1 ) ) ) マクロでは @foo(x+1) と書ける @foo x+1 のようにも書ける マクロは関数と違って健全であるという特徴もある 説明は次頁 15 / 38
  • 16. 変数捕捉と健全な (hygienic) マクロ マクロは AST を変換(マクロ展開)して、新しい AST を呼び 出し元に貼り付ける 展開された AST に含まれる名前が、呼び出し元の文脈にある ものと衝突する事がある(=変数捕捉) 1 必要な名前が呼び出し元で別の値に束縛されている事がある 2 呼び出し元の変数を再束縛してしまう 名前の付け方に細工をすることで回避する 1 マクロが定義されているモジュール名を使って名前を修飾する 2 変数に値を代入するときは、重複しない(今まで作られていな くて、これからも作られない)名前を生成して変数名とする Base.gensym で生成可能 Julia のマクロ展開では全て自動でやってくれる(健全なマ クロ) 16 / 38
  • 17. 変数捕捉と健全なマクロ Base.macroexpand を使うとマクロ展開した結果を得ること ができる 関数なので quote が必要 1 module JT3 # 以 下 全 て の マ ク ロ は こ の モ ジ ュ ー ル 内 に あ る 2 macro setx_A () 3 :( x = sin (1.0) ) 4 end 5 end 1 julia > macroexpand( :( JT3.@setx_A ) ) 2 :(#30#x = JT3.sin (1.0)) 1 sin を JT3 で修飾することで、呼び出し元が sin を隠蔽して いるかどうかを気にしなくてよくなる JT3.sin は(名前の隠蔽をしていなければ)Base.sin になる 2 #30#x という名前を作ることで、呼び出し元に x があるかど うかを気にしなくてよくなる 17 / 38
  • 18. 変数捕捉と健全なマクロ 1 macro setx_A () 2 :( x = sin (1.0) ) 3 end Julia が自動的に x を保護してくれるために、残念ながらこの マクロを使っても呼び出し元の x に変化はおきない 1 julia > x 2 ERROR: UndefVarError : x not defined 3 4 julia > JT3.@setx_A 5 0.8414709848078965 6 7 julia > x 8 ERROR: UndefVarError : x not defined 呼び出し元に影響をあたえるためには、名前の保護を無効化す ることで意図的に変数捕捉を起こす必要がある (Base.esc) 18 / 38
  • 19. 意図的な変数捕捉 Symbol や Expr に Base.esc を作用させると、それらに含ま れる名前は保護されなくなる @setx_B のようにまとめてエスケープしてもよいし @setx_C のように個別にエスケープしてもよい Base.esc が引数にとれるのは Symbol か Expr だけなので:x と quote が必要 esc(:x) の結果を埋め込むために$() が必要 1 macro setx_B () 2 esc( :( x = sin (1.0)) ) 3 end 4 macro setx_C () 5 :( $(esc(:x)) = sin (1.0) ) 6 end 1 julia > macroexpand (:( JT3.@setx_B ) ) 2 :(x = sin (1.0)) 3 4 julia > macroexpand (:( JT3.@setx_C ) ) 5 :(x = JT3.sin (1.0)) 19 / 38
  • 20. 意図的な変数捕捉 このマクロを使うと x の値を変えることができる 1 julia > x 2 ERROR: UndefVarError : x not defined 3 4 julia > JT3.@setx_B 5 0.8414709848078965 6 7 julia > x 8 0.8414709848078965 9 10 julia > x = 0; 11 12 julia > JT3.@setx_C 13 0.8414709848078965 14 15 julia > x 16 0.8414709848078965 20 / 38
  • 21. 潔癖症レベルで健全 マクロ引数に含まれている変数名も全て保護される つまり呼び出し元とは関係ないものとなる まず確実に esc が必要 Symbol のまま残したいときはエスケープしなくても良い ぶっちゃけ迷惑 1 macro setf_A(ex , val) 2 :( $ex = $val ) 3 end 1 julia > macroexpand (:( JT3.@setf_A x y) ) 2 :(#8#x = JT3.y) 3 4 julia > x, y = 0, 42; 5 6 julia > JT3.@setf_A x y 7 ERROR: UndefVarError : y not defined 21 / 38
  • 22. 回避例 基本的にやることはさっきと同じ 今回の@setf_C のように、あらかじめ外でエスケープしてか ら quote 文に注入することもできる 自分の好みで、見やすいものを使ってください 1 macro setf_B(ex , val) 2 esc (:( $ex = $val )) 3 end 4 5 macro setf_C(ex , val) 6 esc_ex = esc(ex) 7 esc_val = esc(val) 8 :( $esc_ex = $esc_val) 9 end 1 julia > macroexpand (:( JT3.@setf_B x y)) 2 :(x = y) 22 / 38
  • 23. 近未来 この「健全すぎる」という件は Julia-0.4 のリリースまでには 修正される予定 マクロに渡された式中の名前が保護されなくなる (あまりないと思うけれど)保護したくなったら自分で gensym やモジュール名修飾すること Base.@hygienic に関数定義を食わせるとその関数でも名前保 護が行われる Issue #6910, #10940 2015-04-25 現在では merge されていないので注意 moon/hygienic-macros branch をビルドすれば試せる 1 macro setf_A(ex , val) 2 :( $ex = $val ) 3 end 1 julia -future > macroexpand (:( JT3.@setf_A x y )) 2 :(x = y) 23 / 38
  • 24. 近未来 もちろん直に書いた名前は今までどおり保護されることとなる Symbol は$:x とすることでお手軽にエスケープできる 1 macro setx_A () 2 :( x = sin (1.0) ) 3 end 4 macro setx_D () 5 :( $:x = sin (1.0) ) 6 end 1 julia -future > macroexpand (:( JT3.@setx_A )) 2 :(#3#x = JT3.sin (1.0)) 3 julia -future > macroexpand (:( JT3.@setx_D )) 4 :(x = JT3.sin (1.0)) 24 / 38
  • 25. 近未来 従来の Base.esc も当然使えるけれど、バグっている? 改めて議論の流れを確認してから報告します 1 macro setx_B () 2 esc( :( x = sin (1.0)) ) 3 end 4 5 macro setx_C () 6 :( $(esc(:x)) = sin (1.0) ) 7 end 1 julia -future > macroexpand (:( JT3.@setx_B )) 2 :(#4#x = JT3.sin (1.0)) 3 4 julia -future > macroexpand (:( JT3.@setx_B )) 5 :(x = JT3.sin (1.0)) 25 / 38
  • 26. Outline 1 Symbol 型と Expr 型 – Julia の抽象構文木 2 マクロシステム 3 メタプログラミング – どう使うか 26 / 38
  • 27. マクロの効用 – 評価タイミングの制御 マクロ呼出しでは式を式のまま、値に評価せずに渡すので、評 価タイミングを自分で制御できる 評価しなかったり、複数回評価したりも可能 与えた式の実行にかかる時間を計測する@time では、現在時刻 を調べる操作を前後にやる必要がある Expr や無名関数にくるむことで関数でもほぼ同じことができ るが、呼び出し側がいちいちそれをやるのは面倒臭すぎる 1 macro time(ex) 2 quote 3 t0 = time_ns () 4 val = $(esc(ex)) 5 t1 = time_ns () 6 println (1.e-9(t1 -t0), "␣sec") 7 val 8 end 9 end 27 / 38
  • 28. マクロの効用 – コンパイル時計算 マクロ展開は式のパース及び関数の JIT コンパイル時に行われ て、構文そのものが書き換わる そのため、定数などをコンパイル時に計算をおこなうことで実 行時間を短くすることができうる 1 function isnotcomment(line) 2 !ismatch(r"^s*(#|$)", line) 3 end 4 function isnotcomment_nomacro (line) 5 !ismatch(Regex("^s*(#|$)"), line) 6 end 文字列リテラルの直前に文字を置くと、自動的にマクロ呼出し になる @r_str は正規表現を作るマクロ 1 julia > foo"hoge" 2 ERROR: UndefVarError : @foo_str not defined 28 / 38
  • 29. マクロの効用 – コンパイル時計算 マクロを使わないと毎回正規表現を作ることになる code_llvm 関数を使って LLVM コードにコンパイルすると、 非マクロ版の方が明らかに中身が多いことが分かる マクロ版 1 julia > code_llvm(JT3.isnotcomment , ( ASCIIString ,)) 2 3 define i1 @julia_isnotcomment_44329 (% jl_value_t *) { 4 top: 5 %1 = call i1 @julia_ismatch4396 (% jl_value_t* inttoptr (i64 4591287408 to %jl_value_t *), %jl_value_t* %0, i64 0) 6 %2 = xor i1 %1, true 7 ret i1 %2 8 } 29 / 38
  • 30. マクロの効用 – コンパイル時計算 非マクロ版 1 julia > code_llvm(JT3.isnotcomment_nomacro , ( ASCIIString ,)) 2 3 define i1 @julia_isnotcomment_nomacro_44330 (% jl_value_t *) { 4 top: 5 %1 = alloca [3 x %jl_value_t *], align 8 6 %.sub = getelementptr inbounds [3 x % jl_value_t *]* %1, i64 0, i64 0 7 %2 = getelementptr [3 x %jl_value_t *]* %1, i64 0, i64 2 8 store %jl_value_t* inttoptr (i64 2 to % jl_value_t *), %jl_value_t ** %.sub , align 8 9 %3 = load %jl_value_t *** @jl_pgcstack , align 8 10 %4 = getelementptr [3 x %jl_value_t *]* %1, i64 0, i64 1 11 %.c = bitcast %jl_value_t ** %3 to % jl_value_t* 12 store %jl_value_t* %.c, %jl_value_t ** %4, align 8 13 store %jl_value_t ** %.sub , %jl_value_t *** @jl_pgcstack , align 8 14 store %jl_value_t* null , %jl_value_t ** %2, align 8 15 %5 = load %jl_value_t ** inttoptr (i64 4580071440 to %jl_value_t **), align 16 16 %6 = load %jl_value_t ** inttoptr (i64 4588059808 to %jl_value_t **), align 32 17 %7 = bitcast %jl_value_t* %6 to i32* 18 %8 = load i32* %7, align 8 19 %9 = call %jl_value_t* @julia_call1392 (% jl_value_t* %5, %jl_value_t* inttoptr ( i64 4600855376 to %jl_value_t *), i32 %8) 20 store %jl_value_t* %9, %jl_value_t ** %2, align 8 21 %10 = call i1 @julia_ismatch4396 (% jl_value_t* %9, %jl_value_t* %0, i64 0) 22 %11 = xor i1 %10, true 23 %12 = load %jl_value_t ** %4, align 8 24 %13 = getelementptr inbounds %jl_value_t* %12, i64 0, i32 0 25 store %jl_value_t ** %13, %jl_value_t *** @jl_pgcstack , align 8 26 ret i1 %11 27 } 30 / 38
  • 31. Generated function 4/21 に新しく Base.@generated が導入された ドキュメントも同時に追加された これまでに渡されたことのない型の組み合わせの時は、関数本 体を実行する その時、引数の値は参照できず、自動的に型が得られる 同じ型の組み合わせを再度投げると、本体は実行されず返り値 のみが得られる AST を返すようにすることで、マクロのように使うことがで きる マクロと違い型による多重ディスパッチが働くことが利点 関数本体の処理内容によっては、2 回目以降も実行されること があるらしい 引数の型別にコンパイル時計算が可能 パラメタライズ型の型パラメータに整数などを渡せて、違う整 数では違う型になることを利用すると、数値ごとにコンパイル 時計算しておくことができる 31 / 38
  • 32. Generated function 百聞は一見にしかず Int を 2 回目以降渡した時には println(x) が実行されない こと、 println(x) で値ではなく型が出力されていることに注目 1 @generated function gen_fn(x) 2 println(x) 3 :(x*x) 4 end 1 julia > JT3.gen_fn (3) 2 Int64 3 9 4 5 julia > JT3.gen_fn (3) 6 9 7 8 julia > JT3.gen_fn (5) 9 25 10 11 julia > JT3.gen_fn (3.14) 12 Float64 13 9.8596 32 / 38
  • 33. Generated function – コンパイル時フィボナッチ generated function では再計算しないので、再帰でやっても十 分速い 1 type IntTag{N} end 2 3 @generated function fib{N}(:: IntTag{N}) 4 N < 3 && return 1 5 ret = fib(N-1) + fib(N-2) 6 :( $ret) 7 end 8 9 fib(N:: Integer) = fib(IntTag{N}()) 1 julia > @time JT3.fib (500) 2 elapsed time: 0.714843811 seconds (13 MB allocated) 3 4859788740867454402 4 # 実 は オ ー バ ー フ ロ ー し て い る ( ぉ 5 6 julia > @time JT3.fib (500) 7 elapsed time: 1.2101e-5 seconds (192 bytes allocated) 8 4859788740867454402 33 / 38
  • 34. Generated function – コンパイル時フィボナッチ 再計算していないことは @show ret とかやるとよくわかる あくまでデモ用なので、フィボナッチ数列を作りたい場合は配 列を用意してループを回したほうがよい BigNum などが使えないのでオーバーフローなどに注意 再帰が深くなるとスタックオーバーフローする 1 @generated function fib{N}(:: IntTag{N}) 2 N < 3 && return 1 3 ret = fib(N-1) + fib(N-2) 4 @show N, ret 5 :( $ret) 1 julia > JT3.fib (100); 2 (N,ret) = (3,2) 3 (N,ret) = (4,3) 4 (N,ret) = (5,5) 5 (N,ret) = (6,8) 6 # 中 略 7 (N,ret) = (98 ,6174643828739884737) 8 (N,ret) = (99 , -2437933049959450366) # Oops 9 (N,ret) = (100 ,3736710778780434371) 34 / 38
  • 36. 関数定義 関数定義も AST で表せるので、関数の自動生成なんてことも できる 形がほとんど同じで、部品(使う関数など)の名前だけが違う 関数群などでは是非 1 type MyFloat 2 val :: Float64 3 end 4 for fn in (:sin , :cos , :tan) 5 eval(Expr (:import , :Base , fn)) 6 @eval ($fn)(mf:: MyFloat) = ($fn)(mf. val) 7 end 36 / 38
  • 37. 関数定義をジャックするマクロ 関数定義を自動的に別の関数定義に置き換えるマクロを作るこ ともできる 自動ロギング、メモ化、末尾再帰最適化などなど 一度に展開形にするのはまず無理 受け取った Expr 型のオブジェクトから関数名や引数名などを 抽出する必要がある いっそオブジェクトの追記・書き換えで完成させるのもアリ 渡された関数定義を、名前を変えて実行してしまい、新しく作 る関数の中から呼ぶのも有効 この場合でも「最後にはこう展開されて欲しい」という対応関 係を最初に考えるのが大事 メモ化や末尾再帰最適化など、そもそもどうやって実現するの かを考えるところから始まる 基本的には macroexpand で結果を確認したり、dump, @show で中身を見ながら試行錯誤 成果物が役立つかは別としても、かなり勉強・練習になる サンプルとしてメモ化マクロを作ってみたので興味があれば ちなみに Memoize.jl なんていうパッケージも既に存在する 37 / 38
  • 38. まとめ Julia の構文を Julia の中からいじる方法(メタプログラミン グ)を見てきた コードを自動生成することで全体のコード量や実装時間を減ら せる マクロや@generated でコンパイル時計算をしたり Memoize.jl などで関数を自動メモ化したりすることで実行性 能をあげられる(かもしれない) 自分で書く場合、どういう結果が出て欲しいかをまず考える macroexpand, dump, @show あたりを駆使して試行錯誤 参考資料 Julia 公式 Document 英語が読めるならこれを読みながら手を動かせばよい On Lisp, (著: Paul Graham, 和訳:野田開) Lisp 系の言語を学ぶと Julia が多大な影響を受けていることがよ くわかる マクロだけじゃなくてクロージャなどの理解にも役立つ 38 / 38