おはこんばんにちは!(死語)
まぁじです。ちょっと@chmaxを使う機会があったので書いてみます。
はじめに
実行環境は以下の通りです。AtCoderのコードテスト(version 1.4.0)でも動くことを確認しました。
$ julia --version julia version 1.3.1
注意・マクロはコードの一番上に置いた方がいいです。
実行する関数より前にないとエラーが出ます。
chmax, chminについて
change maximum/minimumの略で、
chmax(a,b)
はa=max(a,b)
と同じ働きchmin(a,b)
はa=min(a,b)
と同じ働き
これを用いてコードを短くしたりミスを減らしたりします。
ちなみに、人によってはさらに値を交換したかでtrue/falseを返すこともありますが、今回はそちらは書きません。 けんちょんさんの記事などにC++のコードがありますのでそちらを参考にしてください。
Juliaのmacroについて
マクロは以下のように使います。$を用いると変数や式の展開ができます。
macro hoge(a, b, ...) :($a * $b) # ここに処理を書く end # 実行するときにはマクロ名の前に@をつける @hoge(1, 2, ...) # 関数の実行と同様 # もしくはこう書いてもいい @hoge 1 2 ... # 引数をスペースで区切る
また、マクロの展開後に変数名が衝突すると自動で名前が置き換わるのですが、esc関数を用いて既存の変数を呼び出すことができます。
julia> macro hoge2(a,b) esc(:($a=$a*$b)) # aにa*bを代入するマクロ end @hoge2 (macro with 1 method) julia> num=10 10 julia> @hoge2(num,10) # num=num*10=100 100
マクロは関数とは違い、引数を評価せずに実行します。なので値ではなく式を渡すときは注意してください。
chmax, chminの簡単な実装
これを踏まえてそのまま実装してみます。(ハイライトが全然効かない…)
# ifを用いたchmax macro chmax1(a,b) esc(:( if a<b $a=$b end )) end # max関数を用いたchmax macro chmax2(a,b) esc(:($a=max($a,$b))) end # ifを用いたchmin macro chmin1(a,b) esc(:( if a>b $a=$b end )) end # min関数を用いたchmin macro chmin2(a,b) esc(:($a=min($a,$b))) end
a=1として試してみましょう。
julia> @chmax1(a,2) julia> a 2 julia> @chmin1(a,-1) julia> a -1
きちんとマクロが動いています。
chmax, chminを一つのマクロにする
マクロの引数として、変数や式のほか関数も与えることができるので、
- minを与えたらchmin
- maxを与えたらchmax
という風に改造してみましょう。
macro chmaxmin(f,a,b) esc(:($a=$f($a,$b))) end
マクロ名は@chmaxmin
とでもしておきます。(長すぎる気もしますが)
a=1として実行してみます。正常に動いています。
julia> @chmaxmin(max,a,10) 10 julia> @chmaxmin(min,a,-100) -100
たのしい競技プログラミングを!ありがとうございました。