【Crystal】Macroについて
by
at_grandpa
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Macroについて 2018.06.21 @at_grandpa Crystal 勉強会 #6 in 渋谷
Slide 2
Slide 2 text
@at_grandpa
Slide 3
Slide 3 text
圧倒亭グランパのブログ
Slide 4
Slide 4 text
Crystal Advent Calendar 2017
Slide 5
Slide 5 text
Crystal Advent Calendar 2017
Slide 6
Slide 6 text
Macroについて
Slide 7
Slide 7 text
✔ Macro の雰囲気を話します ✔ 細かい syntax などはドキュメント参照
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
✔ 「Crystalのコード」を書くコード ✔ コンパイル前に実行される Macro
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
Macro定義
Slide 12
Slide 12 text
Macro呼出
Slide 13
Slide 13 text
Macro呼出 Macro展開
Slide 14
Slide 14 text
Macro展開後のコードがコンパイルされる
Slide 15
Slide 15 text
どういった利点があるのか
Slide 16
Slide 16 text
✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい
Slide 17
Slide 17 text
重複を排除しやすい
Slide 18
Slide 18 text
No content
Slide 19
Slide 19 text
重複
Slide 20
Slide 20 text
重複
Slide 21
Slide 21 text
重複 重複排除
Slide 22
Slide 22 text
getter だけなのに複雑では…
Slide 23
Slide 23 text
getterあります Object クラスに定義されている Macro
Slide 24
Slide 24 text
便利 Macro たくさん! https://crystal-lang.org/api/Object.html
Slide 25
Slide 25 text
Crystal Advent Calendar 2017 便利 Macro 紹介してます
Slide 26
Slide 26 text
重複を排除しやすい ✔ ある程度は重複排除できる ✔ 便利 Macro がすでにいくつかある
Slide 27
Slide 27 text
メタプロ風味
Slide 28
Slide 28 text
✔ rubyだと instance_methods と define_method ? 各メソッドの実行時間を出力したい! お題
Slide 29
Slide 29 text
簡単なライブラリクラスを書いてみる 「MethodProf」クラスとでも名付けよう
Slide 30
Slide 30 text
まずは使用例
Slide 31
Slide 31 text
出来上がりイメージ
Slide 32
Slide 32 text
出来上がりイメージ 1秒 sleep して String を返す
Slide 33
Slide 33 text
出来上がりイメージ 100万回 String を結合する
Slide 34
Slide 34 text
出来上がりイメージ 100万回 String を2つ結合している
Slide 35
Slide 35 text
出来上がりイメージ MethodProf を include して Macro を展開している
Slide 36
Slide 36 text
出来上がりイメージ インスタンスを生成してメソッド呼び出し
Slide 37
Slide 37 text
出来上がりイメージ
Slide 38
Slide 38 text
MethodProf クラス
Slide 39
Slide 39 text
No content
Slide 40
Slide 40 text
macro構文で定義(引数はio)
Slide 41
Slide 41 text
・@type は型情報にアクセスできる ・@type.methods で型に定義されているmethodの配列を得る - ArrayLiteral(Crystal::Macros::Def) ・initializeメソッドは計測対象から外すので配列から除去 → initialize 以外の method 情報で for を回す
Slide 42
Slide 42 text
・展開される Crystal のコードを定義 ・呼出先に def 構文が展開される
Slide 43
Slide 43 text
・メソッド名は Crystal::Macros::Def#name で得る ・引数は Crystal::Macros::Def#args で得る - 「*」をつけて splat展開 している
Slide 44
Slide 44 text
・計測のために時間を保持
Slide 45
Slide 45 text
・lambda を生成 - 引数は対象のメソッドと同じ - メソッドの中身は Crystal::Macros::Def#body で得る ・lambda を即座に call する - 渡す引数は args の名前を羅列 - *(m.args) は型情報も含まれてしまうので、ここでは名前だけ展開 ・return_value に格納
Slide 46
Slide 46 text
・計測結果を io に出力
Slide 47
Slide 47 text
・lambda の結果を返す
Slide 48
Slide 48 text
Macro を展開するとこうなります loop2を例に
Slide 49
Slide 49 text
Macro定義 loop2展開後
Slide 50
Slide 50 text
Macro定義 loop2展開後
Slide 51
Slide 51 text
Macro定義 loop2展開後
Slide 52
Slide 52 text
Macro定義 loop2展開後
Slide 53
Slide 53 text
Macro定義 loop2展開後
Slide 54
Slide 54 text
Macro定義 loop2展開後
Slide 55
Slide 55 text
✔ ASTNodeの情報からコンパイル時にコードを生成 ✔ splat展開が優秀だった! ✔ もちろん「動的なclass定義」はできない メタプロ風味
Slide 56
Slide 56 text
DSLを提供しやすい
Slide 57
Slide 57 text
https://github.com/at-grandpa/clim
Slide 58
Slide 58 text
https://github.com/at-grandpa/clim ✔ ruby の thor 風 syntax ✔ オプションの型指定 ✔ default / required ✔ サブコマンド ✔ カスタムヘルプ
Slide 59
Slide 59 text
No content
Slide 60
Slide 60 text
No content
Slide 61
Slide 61 text
No content
Slide 62
Slide 62 text
すべて Macro ・最終的に全てクラスやメソッドの定義に展開される
Slide 63
Slide 63 text
No content
Slide 64
Slide 64 text
コンパイル時に raise で落としてエラーメッセージを出す
Slide 65
Slide 65 text
DSLに渡された文字列を使ってオプションの独自のクラスを定義 DSLに渡された文字列を使ってコマンドの独自のクラスを定義
Slide 66
Slide 66 text
DSLを提供しやすい ✔ 複雑なコードも簡単に記述できるようになる
Slide 67
Slide 67 text
✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい Macro の利点おさらい
Slide 68
Slide 68 text
Macro周りのtips
Slide 69
Slide 69 text
デバッグしづらいのでは?
Slide 70
Slide 70 text
エラー文が親切です!
Slide 71
Slide 71 text
エラー文が親切です! Macro 展開後のどこでエラーが起きているかわかる
Slide 72
Slide 72 text
エラー文が親切です! エラー内容も具体的
Slide 73
Slide 73 text
`crystal tool expand` があります! ✔ ファイルとカーソル位置指定 ✔ カーソル位置の Macro を展開して表示
Slide 74
Slide 74 text
crystal tool expand ファイルとカーソル位置を指定
Slide 75
Slide 75 text
crystal tool expand 展開されたコードを見ることができる
Slide 76
Slide 76 text
`macro` ディレクティブなしでもOK
Slide 77
Slide 77 text
実は直接書けます 環境変数でcrystalコードを切り替えたりできます
Slide 78
Slide 78 text
展開後は正しいのにエラーなんだけど
Slide 79
Slide 79 text
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい
Slide 80
Slide 80 text
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい
Slide 81
Slide 81 text
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい この Macro 展開だけでは `when` だけしか展開されない → Macro展開だけのコードを見ると syntax error → コンパイラ落ちる
Slide 82
Slide 82 text
begin ~ end を使う
Slide 83
Slide 83 text
begin ~ end を使う begin ~ end で囲めば、 ひとつのMacroとして扱われる → 展開後のコードは正しい ※ 実は {% begin %} は {% if true %} のシンタックスシュガーです
Slide 84
Slide 84 text
まとめ
Slide 85
Slide 85 text
✔ 「Crystalのコード」を書くコード ✔ コンパイル前に実行される ✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい Macro とは
Slide 86
Slide 86 text
Happy Crystalling fin