はじめに
最近SNSでギリギリダンスの動画がよく回ってきます。
参考動画:https://www.youtube.com/watch?v=jzi6RNVEOtA
その動画の中で”... --- ...”というモールス信号が使われています。
このモールス信号がプログラムの中でも使えたら面白いのではないかと思い、
今回モールス信号を入力するとアルファベットに変換されるマクロを実装しました。
Rustのマクロの前提知識については下記素晴らしい記事で補填いただくとして、
割愛させていただきます。
参考記事:https://qiita.com/k5n/items/758111b12740600cc58f
コード解説
1.実行結果
まずは実装したマクロ「morse!」の使い方について説明します。
- 引数 :可変数、文字列でモールス信号を与える
- 戻り値:なし
- 処理 :引数に対応するアルファベットを表示する、対応がなければ"#"を表示する
fn main() {
//実行例1
print!("morse signal to alphabet : ");
morse!("....", ".-", ".--.", ".--.", "-.--");
println!();
//実行例2
print!("morse signal to alphabet : ");
morse!(".-.", "..-", "...", "-");
println!();
//実行例3
print!("ギリギリダンス : ");
morse!("...", "---", "...");
println!();
//実行例4
print!("NG : ");
morse!("2", "A", ".....");
}
morse signal to alphabet : HAPPY
morse signal to alphabet : RUST
ギリギリダンス : SOS
NG : ###
2.実装したマクロ
実装したマクロの全体像になります。
use std::collections::HashMap;
#[macro_export]
macro_rules! morse {
( $ ($term:tt),* ) => {
{
//モールス信号の対応テーブルを作成する
let mut morse_table = HashMap::new();
morse_table.insert(".-", "A"); morse_table.insert("-...", "B"); morse_table.insert("-.-.", "C");
morse_table.insert("-..", "D"); morse_table.insert(".", "E"); morse_table.insert("..-.", "F");
morse_table.insert("--.", "G"); morse_table.insert("....", "H"); morse_table.insert("..", "I");
morse_table.insert(".---", "J"); morse_table.insert("-.-", "K"); morse_table.insert(".-..", "L");
morse_table.insert("--", "M"); morse_table.insert("-.", "N"); morse_table.insert("---", "O");
morse_table.insert(".--.", "P"); morse_table.insert("--.-", "Q"); morse_table.insert(".-.", "R");
morse_table.insert("...", "S"); morse_table.insert("-", "T"); morse_table.insert("..-", "U");
morse_table.insert("...-", "V"); morse_table.insert(".--", "W"); morse_table.insert("-..-", "X");
morse_table.insert("-.--", "Y"); morse_table.insert("--..", "Z");
//信号 → アルファベットに変換する
$(
match morse_table.get($term) {
Some(morse_alphabet) => print!("{}", morse_alphabet),
None => print!("#"),
}
) *
}
};
}
2.1モールス信号の対応テーブルの実装
HashMap(連想配列)を使用して愚直にモールス信号とアルファベットの対応をコーディングしました。
※ほかに良い方法があればご教授ください。
//モールス信号の対応テーブルを作成する
let mut morse_table = HashMap::new();
morse_table.insert(".-", "A"); morse_table.insert("-...", "B"); morse_table.insert("-.-.", "C");
morse_table.insert("-..", "D"); morse_table.insert(".", "E"); morse_table.insert("..-.", "F");
morse_table.insert("--.", "G"); morse_table.insert("....", "H"); morse_table.insert("..", "I");
morse_table.insert(".---", "J"); morse_table.insert("-.-", "K"); morse_table.insert(".-..", "L");
morse_table.insert("--", "M"); morse_table.insert("-.", "N"); morse_table.insert("---", "O");
morse_table.insert(".--.", "P"); morse_table.insert("--.-", "Q"); morse_table.insert(".-.", "R");
morse_table.insert("...", "S"); morse_table.insert("-", "T"); morse_table.insert("..-", "U");
morse_table.insert("...-", "V"); morse_table.insert(".--", "W"); morse_table.insert("-..-", "X");
morse_table.insert("-.--", "Y"); morse_table.insert("--..", "Z");
2.2信号をアルファベットに変換する
HashMapで定義したモールス信号対応テーブルから引数「term」に対応するアルファベット取得を試みます。対応がある/なしに応じてmatch文で処理しています。
可変数引数をとるため、ここの処理は「$()*」で囲い、与えられた引数の分だけ繰り返します。
//信号 → アルファベットに変換する
$(
match morse_table.get($term) {
Some(morse_alphabet) => print!("{}", morse_alphabet),
None => print!("#"),
}
) *
終わりに
これで簡単にモールス信号をプログラム内で使うことができるようになりました。
Rustのマクロは可変数引数を簡単に実装できるのが大変便利ですね。
しかもマクロを書くのは楽しい、、
これからもテーマを見つけて楽しいマクロを実装していければと思います。
以上です!