Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
【Crystal】Macroについて
Search
at_grandpa
June 21, 2018
Technology
1.5k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
【Crystal】Macroについて
東京 Crystal 勉強会 #6 in 渋谷
https://crystal.connpass.com/event/90745/
イベント資料です。
at_grandpa
June 21, 2018
More Decks by at_grandpa
See All by at_grandpa
技術書典5でチャレンジしたあれこれ
atgrandpa
3
2k
CSS組版おもしろい!
atgrandpa
1
340
Rubyを好きになった過程
atgrandpa
3
1.6k
技術同人誌を執筆して得たこと
atgrandpa
3
1.6k
【Crystal】Concurrency
atgrandpa
3
950
初のサークル参加で気づいた小さなこと
atgrandpa
0
510
Other Decks in Technology
See All in Technology
発表と総括 / Presentations and Summary
ks91
PRO
0
140
SRE依存からの脱却 運用を開 発チームへ移す、 フルサイ クル開 発体制の実践
joooee0000
0
3.2k
誤解だらけの開発生産性 / Myths and Misconceptions about Developer Productivity
i35_267
2
810
しくみを学んで使いこなそう GitHub Copilot app
torumakabe
2
290
非定型なドキュメントを効率よくリファクタする 〜えぇ!?仕様書27本の移行が1日で終わったって!?〜
subroh0508
2
560
変更し続けられるシステムをどう保つか — AI時代のSSoTという設計原則
kawauso
0
130
大量データに対しても、生成AIを用いてリーズナブルにデータ加工をしたい!Databricksのai_queryについて調べてみた
kamoshika
1
220
【Claude Code】鹿野さんに聞く 私の推しの並行開発環境 大公開 / claude-code-parallel-2026-07-15
tonkotsuboy_com
12
8.7k
SoccerMaster: A Vision Foundation Model for Soccer Understanding
kzykmyzw
0
140
LLMやAIエージェントをソフトウェアに組み込むプラクティス
shibuiwilliam
2
420
ZOZOTOWNの進化と信頼性を両立する負荷試験
zozotech
PRO
2
220
タスクの複雑さでモデルを選ぶ ── Thompson Samplingで動かす“トークン/コスト最適化
satohy0323
0
560
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
55
10k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
KATA
mclloyd
PRO
35
15k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
250
Navigating Team Friction
lara
192
16k
Writing Fast Ruby
sferik
630
63k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
220
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.7k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
190
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Statistics for Hackers
jakevdp
799
230k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.3k
Transcript
Macroについて 2018.06.21 @at_grandpa Crystal 勉強会 #6 in 渋谷
@at_grandpa
圧倒亭グランパのブログ
Crystal Advent Calendar 2017
Crystal Advent Calendar 2017
Macroについて
✔ Macro の雰囲気を話します ✔ 細かい syntax などはドキュメント参照
None
✔ 「Crystalのコード」を書くコード ✔ コンパイル前に実行される Macro
None
Macro定義
Macro呼出
Macro呼出 Macro展開
Macro展開後のコードがコンパイルされる
どういった利点があるのか
✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい
重複を排除しやすい
None
重複
重複
重複 重複排除
getter だけなのに複雑では…
getterあります Object クラスに定義されている Macro
便利 Macro たくさん! https://crystal-lang.org/api/Object.html
Crystal Advent Calendar 2017 便利 Macro 紹介してます
重複を排除しやすい ✔ ある程度は重複排除できる ✔ 便利 Macro がすでにいくつかある
メタプロ風味
✔ rubyだと instance_methods と define_method ? 各メソッドの実行時間を出力したい! お題
簡単なライブラリクラスを書いてみる 「MethodProf」クラスとでも名付けよう
まずは使用例
出来上がりイメージ
出来上がりイメージ 1秒 sleep して String を返す
出来上がりイメージ 100万回 String を結合する
出来上がりイメージ 100万回 String を2つ結合している
出来上がりイメージ MethodProf を include して Macro を展開している
出来上がりイメージ インスタンスを生成してメソッド呼び出し
出来上がりイメージ
MethodProf クラス
None
macro構文で定義(引数はio)
・@type は型情報にアクセスできる ・@type.methods で型に定義されているmethodの配列を得る - ArrayLiteral(Crystal::Macros::Def) ・initializeメソッドは計測対象から外すので配列から除去 → initialize 以外の
method 情報で for を回す
・展開される Crystal のコードを定義 ・呼出先に def 構文が展開される
・メソッド名は Crystal::Macros::Def#name で得る ・引数は Crystal::Macros::Def#args で得る - 「*」をつけて splat展開 している
・計測のために時間を保持
・lambda を生成 - 引数は対象のメソッドと同じ - メソッドの中身は Crystal::Macros::Def#body で得る ・lambda を即座に
call する - 渡す引数は args の名前を羅列 - *(m.args) は型情報も含まれてしまうので、ここでは名前だけ展開 ・return_value に格納
・計測結果を io に出力
・lambda の結果を返す
Macro を展開するとこうなります loop2を例に
Macro定義 loop2展開後
Macro定義 loop2展開後
Macro定義 loop2展開後
Macro定義 loop2展開後
Macro定義 loop2展開後
Macro定義 loop2展開後
✔ ASTNodeの情報からコンパイル時にコードを生成 ✔ splat展開が優秀だった! ✔ もちろん「動的なclass定義」はできない メタプロ風味
DSLを提供しやすい
https://github.com/at-grandpa/clim
https://github.com/at-grandpa/clim ✔ ruby の thor 風 syntax ✔ オプションの型指定 ✔
default / required ✔ サブコマンド ✔ カスタムヘルプ
None
None
None
すべて Macro ・最終的に全てクラスやメソッドの定義に展開される
None
コンパイル時に raise で落としてエラーメッセージを出す
DSLに渡された文字列を使ってオプションの独自のクラスを定義 DSLに渡された文字列を使ってコマンドの独自のクラスを定義
DSLを提供しやすい ✔ 複雑なコードも簡単に記述できるようになる
✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい Macro の利点おさらい
Macro周りのtips
デバッグしづらいのでは?
エラー文が親切です!
エラー文が親切です! Macro 展開後のどこでエラーが起きているかわかる
エラー文が親切です! エラー内容も具体的
`crystal tool expand` があります! ✔ ファイルとカーソル位置指定 ✔ カーソル位置の Macro を展開して表示
crystal tool expand ファイルとカーソル位置を指定
crystal tool expand 展開されたコードを見ることができる
`macro` ディレクティブなしでもOK
実は直接書けます 環境変数でcrystalコードを切り替えたりできます
展開後は正しいのにエラーなんだけど
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい
❌ Macro展開後、全体のコードが正しい ⭕ Macro展開のみで出来たコードが正しい この Macro 展開だけでは `when` だけしか展開されない →
Macro展開だけのコードを見ると syntax error → コンパイラ落ちる
begin ~ end を使う
begin ~ end を使う begin ~ end で囲めば、 ひとつのMacroとして扱われる →
展開後のコードは正しい ※ 実は {% begin %} は {% if true %} のシンタックスシュガーです
まとめ
✔ 「Crystalのコード」を書くコード ✔ コンパイル前に実行される ✔ 重複を排除しやすい ✔ メタプロ風味 ✔ DSLを提供しやすい
Macro とは
Happy Crystalling fin