Julia - 関数の broadcast ( f.(arg...) ) をオーバーロードする方法

どこで使うと便利なのかわからないけれど、一応できたのでメモ。
公式ドキュメントだけでこの方法を思いつく人は相当訓練された Julian だと思う(思いたい)。

Julia 1.0 でのやり方

f.(arg...) の挙動を変えたい場合、broadcast でなく、broadcastedオーバーロードすれば良い。

julia> f(x) = println("Normal")
f (generic function with 1 method)

julia> f(1)
Normal

julia> f.(1)
Normal

# 第一引数を `::typeof(挙動を変えたい関数)` とするのがミソ
julia> Base.Broadcast.broadcasted(::typeof(f), x) = println("Broadcast")

julia> f(1)
Normal

julia> f.(1)
Broadcast

julia> f.([1,2])
Broadcast

上手くいかない方法

ドキュメントに

A special syntax exists for broadcasting: f.(args...) is equivalent to broadcast(f, args...)

とあるけど、broadcastオーバーロードすればいいわけではない。

Arrays · The Julia Language

julia> f(x) = println("Normal")
f (generic function with 1 method)

julia> f(1)
Normal

julia> f.(1)
Normal

julia> f.(x::Int) = println("Broadcast")
ERROR: syntax: invalid syntax "f.(x::Int) = ..."

julia> Base.broadcast(f, x::Int)= println("Broadcast")

julia> f(1)
Normal

julia> f.(1)
Normal

julia> Base.broadcast(::typeof(f), x::Int)= println("Broadcast")

julia> f.(1)
Normal

julia> f.([1,2])
Normal
Normal
2-element Array{Nothing,1}:
 nothing
 nothing

Julia 0.6 のときは broadcastオーバーロードすればよかった。

julia> f(x) = println("Default")
f (generic function with 1 method)

julia> f(1)
Default

julia> f.(1)
Default

julia> Base.broadcast(::typeof(f), x) = println("Broadcast")

julia> f(1)
Default

julia> f.(1) # ここの挙動が Julia 1.0 と違う
Default

julia> f.([1, 2])
Broadcast

参考

x.*x not customizable · Issue #22053 · JuliaLang/julia · GitHub

Interfaces · The Julia Language