Edited at

Julia で a == 1 && a == 2 && a == 3 を true にする

More than 1 year has passed since last update.

StackOverflow で話題になった記事が他の言語版に派生しているようなので取調中の Julia 0.6.2 でも。

元ネタ: https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true

動的型付き言語ながら多重ディスパッチではスパルタンな型検査が行われる点などが気に入っている Julia ですが、マクロで AST (抽象構文木) を扱える言語なのでマクロで書き換えます。ありきたりですみません (だがタイトルは間違っていない!)。

macro 🍣(expr)

if expr.head == :if && expr.args[1] == :(a == 1 && a == 2 && a == 3)
expr.args[1] = :(true)
end
expr
end

a = 1
@🍣 if a == 1 && a == 2 && a == 3
println("真")
else
println("偽")
end
# ==> 真

(マクロ識別子の🍣に特に意味はありません) 見ての通り a==1 && a==2 && a==3 を条件に持つ if 文に付けられていたらその条件部分を固定値 true に置き換えるだけです。

三項演算子 exp? A: Bif 構文と解釈されるので使えます。

@🍣 (a == 1 && a == 2 && a == 3)? println("真"): println("偽")

# ==> 真

ただし println() 内で条件式を記述した AST はこのマクロでは機能しません。葉方向に下ってないからね。

@🍣 println(a == 1 && a == 2 && a == 3? "真": "偽")

# ==> 偽

条件文に付ければ OK

println(@🍣 a == 1 && a == 2 && a == 3? "真": "偽")

# ==> 真

寿司マクロが何をやっているかというと、構文解析で AST に展開された if の条件評価部分が args[1] であるため、そこを true に置き換えてコードを if(true) へ変換しているわけです (Julia の配列は 1-origin です)。

ちょっと長いですが if(...) 部分の AST ダンプはこのようになります。AST は Expr という型で表されます。また :(...) は中の構文を AST に変換します。

julia> dump(:(if(a == 1 && a == 2 && a == 3) true else false end))

Expr
head: Symbol if
args: Array{Any}((3,))
1: Expr
head: Symbol &&
args: Array{Any}((2,))
1: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ==
2: Symbol a
3: Int64 1
typ: Any
2: Expr
head: Symbol &&
args: Array{Any}((2,))
1: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ==
2: Symbol a
3: Int64 2
typ: Any
2: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ==
2: Symbol a
3: Int64 3
typ: Any
typ: Any
typ: Any
2: Expr
head: Symbol block
args: Array{Any}((2,))
1: Expr
head: Symbol line
args: Array{Any}((2,))
1: Int64 1
2: Symbol REPL[34]
typ: Any
2: Bool true
typ: Any
3: Expr
head: Symbol block
args: Array{Any}((2,))
1: Expr
head: Symbol line
args: Array{Any}((2,))
1: Int64 1
2: Symbol REPL[34]
typ: Any
2: Bool false
typ: Any
typ: Any

余談ですが、REPL や Jupyter Notebook など、Julia 環境は Unicode の タブ補完シーケンス をサポートしていて、\:sushi:Tab と入力すると 🍣 が入力されます。数学記号を入力しやすくするためですが ZWJ も使えて \:man:Tab \:skin-tone-5:Tab の順で 👨🏾 となります。スゴイ! (誰得)。