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
3
1.5k
【Crystal】Macroについて
東京 Crystal 勉強会 #6 in 渋谷
https://crystal.connpass.com/event/90745/
イベント資料です。
at_grandpa
June 21, 2018
Tweet
Share
More Decks by at_grandpa
See All by at_grandpa
技術書典5でチャレンジしたあれこれ
atgrandpa
3
1.9k
CSS組版おもしろい!
atgrandpa
1
300
Rubyを好きになった過程
atgrandpa
3
1.5k
技術同人誌を執筆して得たこと
atgrandpa
3
1.5k
【Crystal】Concurrency
atgrandpa
3
870
初のサークル参加で気づいた小さなこと
atgrandpa
0
490
Other Decks in Technology
See All in Technology
Transformerを用いたアイテム間の 相互影響を考慮したレコメンドリスト生成
recruitengineers
PRO
2
440
安定した基盤システムのためのライブラリ選定
kakehashi
PRO
3
130
CDK Vibe Coding Fes
tomoki10
1
630
Bill One 開発エンジニア 紹介資料
sansan33
PRO
4
13k
VS CodeとGitHub Copilotで爆速開発!アップデートの波に乗るおさらい会 / Rapid Development with VS Code and GitHub Copilot: Catch the Latest Wave
yamachu
3
460
Snowflake Intelligenceという名のAI Agentが切り開くデータ活用の未来とその実現に必要なこと@SnowVillage『Data Management #1 Summit 2025 Recap!!』
ryo_suzuki
1
160
〜『世界中の家族のこころのインフラ』を目指して”次の10年”へ〜 SREが導いたグローバルサービスの信頼性向上戦略とその舞台裏 / Towards the Next Decade: Enhancing Global Service Reliability
kohbis
3
1.5k
サービスを止めるな! DDoS攻撃へのスマートな備えと最前線の事例
coconala_engineer
1
180
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
18k
ポストコロナ時代の SaaS におけるコスト削減の意義
izzii
1
470
「Chatwork」のEKS環境を支えるhelmfileを使用したマニフェスト管理術
hanayo04
1
400
[SRE NEXT 2025] すみずみまで暖かく照らすあなたの太陽でありたい
carnappopper
2
470
Featured
See All Featured
Six Lessons from altMBA
skipperchong
28
3.9k
Git: the NoSQL Database
bkeepers
PRO
430
65k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.4k
Designing for humans not robots
tammielis
253
25k
4 Signs Your Business is Dying
shpigford
184
22k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
21k
Being A Developer After 40
akosma
90
590k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.7k
For a Future-Friendly Web
brad_frost
179
9.8k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Testing 201, or: Great Expectations
jmmastey
43
7.6k
Making the Leap to Tech Lead
cromwellryan
134
9.4k
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