はるすえすしーのぶろぐ

ブログのないようがないよう

Juliaのchmax, chminマクロについて

おはこんばんにちは!(死語)
まぁじです。ちょっと@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

たのしい競技プログラミングを!ありがとうございました。

参考

Julia Documentation · The Julia Language

お気楽 Julia プログラミング超入門

動的計画法超入門! Educational DP Contest の A ~ E 問題の解説と類題集 - Qiita