Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
2k
CSS組版おもしろい!
atgrandpa
1
320
Rubyを好きになった過程
atgrandpa
3
1.6k
技術同人誌を執筆して得たこと
atgrandpa
3
1.6k
【Crystal】Concurrency
atgrandpa
3
900
初のサークル参加で気づいた小さなこと
atgrandpa
0
500
Other Decks in Technology
See All in Technology
20251218_AIを活用した開発生産性向上の全社的な取り組みの進め方について / How to proceed with company-wide initiatives to improve development productivity using AI
yayoi_dd
0
660
AI with TiDD
shiraji
1
290
[2025-12-12]あの日僕が見た胡蝶の夢 〜人の夢は終わらねェ AIによるパフォーマンスチューニングのすゝめ〜
tosite
0
180
_第4回__AIxIoTビジネス共創ラボ紹介資料_20251203.pdf
iotcomjpadmin
0
130
マイクロサービスへの5年間 ぶっちゃけ何をしてどうなったか
joker1007
21
8.1k
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
1
770
「図面」から「法則」へ 〜メタ視点で読み解く現代のソフトウェアアーキテクチャ〜
scova0731
0
500
『君の名は』と聞く君の名は。 / Your name, you who asks for mine.
nttcom
1
120
Lookerで実現するセキュアな外部データ提供
zozotech
PRO
0
200
Knowledge Work の AI Backend
kworkdev
PRO
0
260
SREが取り組むデプロイ高速化 ─ Docker Buildを最適化した話
capytan
0
150
さくらのクラウド開発ふりかえり2025
kazeburo
2
1.2k
Featured
See All Featured
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
0
22
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
0
310
Code Review Best Practice
trishagee
74
19k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Context Engineering - Making Every Token Count
addyosmani
9
550
The Curse of the Amulet
leimatthew05
0
4.8k
A Modern Web Designer's Workflow
chriscoyier
698
190k
A Soul's Torment
seathinner
1
2k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.4k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
0
210
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Paper Plane (Part 1)
katiecoart
PRO
0
2.1k
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