Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Rust のマクロについて調べてみた
osyo
October 27, 2020
Programming
0
160
Rust のマクロについて調べてみた
osyo
October 27, 2020
Tweet
Share
More Decks by osyo
See All by osyo
5分で話せる Ruby 3.1
osyo
0
47
AST を使って ActiveRecord の where の条件式をブロックで記述しよう
osyo
2
560
Vim の開発環境自慢
osyo
5
2.5k
Use Macro all the time ~ マクロを使いまくろ ~ 感想戦
osyo
0
110
Use Macro all the time ~ マクロを使いまくろ ~ (English)
osyo
3
130
Use Macro all the time ~ マクロを使いまくろ ~ (日本語)
osyo
0
1.5k
月単位でイテレーションする
osyo
0
120
Ruby 3.0 で変わった private と attr_xxx
osyo
1
310
Ruby 2.0 から Ruby 3.0 を駆け足で振り返る
osyo
0
960
Other Decks in Programming
See All in Programming
Java アプリとAWS の良い関係 - AWS でJava アプリを実行する一番簡単な方法教えます / AWS for Javarista
kanamasa
2
1.3k
Client-Side Field-Level Encryption for Apache Kafka Connect @ VoxxedDays Luxembourg 2022
hpgrahsl
0
110
Get Ready for Jakarta EE 10
ivargrimstad
0
2.5k
VisualProgramming_GoogleHome_LINE
nearmugi
1
230
React Nativeアプリを DDDで開発している話
nihemak
0
150
Get Ready for Jakarta EE 10
ivargrimstad
0
800
Licences open source : entre guerre de clochers et radicalité
pylapp
2
510
LINE Messaging APIの概要 - LINE API総復習シリーズ
uezo
1
180
Chart実装が楽になりました。
keisukeyamagishi
0
120
即、New Relic / New Relic NOW!
uzulla
0
330
リアルタイムボイスチェンジャーMMVCとVITSの紹介
stealthinu
0
120
CakePHPの内部実装 から理解するPSR-7
boro1234
0
250
Featured
See All Featured
How to name files
jennybc
40
61k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
351
21k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
212
20k
Bootstrapping a Software Product
garrettdimon
296
110k
Rails Girls Zürich Keynote
gr2m
86
12k
Code Review Best Practice
trishagee
43
9.2k
The MySQL Ecosystem @ GitHub 2015
samlambert
238
11k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
5
510
Reflections from 52 weeks, 52 projects
jeffersonlam
337
17k
For a Future-Friendly Web
brad_frost
166
7.4k
A Philosophy of Restraint
colly
192
15k
Become a Pro
speakerdeck
PRO
3
840
Transcript
Rust LT 会@ オンライン Rust LT 会@ オンライン Rust のマクロについて調べてみた
Rust のマクロについて調べてみた
⾃⼰紹介 ⾃⼰紹介 名前:osyo Twitter : github : ブログ : 元
C++er の現 Rails エンジニア 趣味で Ruby にパッチを投げたりしてる Rust 歴は1 ⽇ 昔 struct + trait でコンパイル時処理で遊んだことはある コンパイル時に階乗を⾏おうとしたりとか… @pink_bangbi osyo-manga Secret Garden(Instrumental) https://osyo-manga.github.io/slide-shinjukurb-58-rust/#/
Rust のマクロについて調べてみた Rust のマクロについて調べてみた
マクロとは マクロとは ソースコード中に繰り返し登場する特定の記述を、別の(短い)記 述に置き換えることができる機能をマクロという。 C / C++ ではプリプロセッサでプリプロセス時に機械的にコードを置 換する機能 Rust
でも同等の機能があるが C / C++ よりもより強⼒な機能になって いる 単純な置換ではなくて構⽂⾃体を拡張できる 構⽂⽊レベルでの拡張ができる(らしい #define PI 3.14 #define PLUS(a, b) a + b auto f = PI + PI; // auto f = 3.14 + 3.14 auto n = PLUS(1, 2) * 3 // auto n = 1 + 2 * 3
簡単な使い⽅ 簡単な使い⽅ macro_rules! 名前 {} でマクロを定義する事ができる ( 引数) => {
展開後のコード } でマクロ本体を記述する // マクロを定義する // hello がマクロ名になる macro_rules! hello { () => { println!("Hello!"); }; } fn main() { // 定義したマクロを呼び出す // hello!() のように ! を付けて関数っぽい呼び出しを⾏う hello!(); // println!("Hello!"); に置き換わる // () ではなくて [] や {} で呼び出すことができる hello![]; // {} の場合は ; がなくてもいいらしい hello!{} }
パターンを定義する パターンを定義する ( パターン) => { ... } で呼び出し元から渡された値を元に処理を分岐す ることができる
macro_rules! animal { // 引数の値で処理を切り分ける (cat) => { " にゃーん" }; (dog) => { " わーん" }; // 再帰的にマクロを呼び出すこともできる (cat and dog) => { animal!(cat).to_string() + " and " + animal! (dog) }; (cat -> dog) => { animal!(cat).to_string() + " to " + animal!(dog) }; } fn main() { // 引数の⽂字列によって呼び出されるマクロの処理が切り替わる println!("{}", animal!(cat)); // output: にゃーん println!("{}", animal!(dog)); // output: わーん println!("{}", animal!(cat and dog)); // output: にゃーん and わーん println!("{}", animal!(cat -> dog)); // output: にゃーん to わーん }
パターンを変数で受け取る パターンを変数で受け取る メタ変数と呼ばれるもので { 変数名: フラグメント指定⼦} で値を受け 取ることができる macro_rules! plus
{ // $a と $b で引数の値を受け取る // expr は『式を受け取る』という意味 // expr はフラグメント指定⼦と呼ばれる ($a: expr, $b: expr) => { $a + $b }; } macro_rules! calc { // 演算⼦も受け取る事ができる ($a: expr, $op: tt, $b: expr) => { $a $op $b }; } fn main() { println!("{}", plus!(1, 2)); // output: 3 println!("{}", plus!(1, 2 * 3)); // output: 7 println!("{}", calc!(1, -, 2)); // output: -1 }
デバッグ⽤のマクロをつくってみる デバッグ⽤のマクロをつくってみる 式とその結果の両⽅を出⼒するマクロを定義する // 式を受け取ってその式の⽂字列と結果を表⽰する macro_rules! debug { // stringify!
で受け取った値を⽂字列に変換できる ($expr: expr) => { println!("{} => {}", stringify!($expr), $expr) } } fn main() { let a = 42; debug!(1 + 2); // output: 1 + 2 => 3 debug!(a + 3); // output: a + 3 => 45 debug!(a.to_string() + "homu"); // a.to_string() + "homu" => 42homu }
マクロのスコープ マクロのスコープ マクロ内のスコープは独⽴しているので変数は外から参照できない macro_rules! test { // マクロ内のスコープは独⽴していて変数は外から参照できない () =>
{ let a = 42; println!("{}", a); }; } fn main() { test!(); // error[E0425]: cannot find value `a` in this scope a; }
マクロの優先順位( 評価順) マクロの優先順位( 評価順) マクロが先に評価される #define test 1 + 2
// 1 + 2 * 3 と展開される test * 3 // 7 macro_rules! test { () => { 1 + 2 }; } fn main() { // (1 + 2) * 3 が評価される println!("{}", test!() * 3); // output: 9 }
まとめ まとめ C / C++ と⽐べて Rust のマクロはかなり強⼒に⾒える この強⼒なマクロを Ruby
で実装したい… まだまだおもしろい使い⽅があると思うので今後も調べていきたい このあたりの話を普段から Rust を使っている⼈からいろいろと 聞いてみたい 実際のユースケースなどなど そもそも Rust のマクロの仕組みが(コンパイラや構⽂レベルで)わ かってないのでそのあたりを今後は理解していきたい
資料 資料 Rust の全マクロ種別が分かったつもりになれる話! / rust-all-kinds-of- macro ためしておぼえる Rust のマクロ
- Qiita Rust のマクロを覚える - Qiita マクロクラブ Rust ⽀部 | κeen のHappy Hacκing Blog
ご清聴 ご清聴 ありがとうございました ありがとうございました