tomtom
February 27, 2020, 4:25am
1
docs said:
f.(args...) is equivalent to broadcast(f, args...)
however, I found that f.() is not calling broadcast(f, ):
Base.broadcast(::typeof(exp), x) = println("exp ", x);
x = [1.0, 2.0];
julia> Base.broadcast(exp, x)
exp [1.0, 2.0]
julia> exp.(x)
2-element Array{Float64,1}:
2.718281828459045
7.3890560989306495
in above, exp.() is not calling the broadcast() I tried to override. Is there any method to enforce it? thanks.
tomtom
February 27, 2020, 6:49am
3
I mean, why f.() not compiled into broadcast(f, ) ?
I don’t know the answer to that, but in case you didn’t know, here’s how to check what is being called:
julia> @code_lowered (()->f.(x))()
CodeInfo(
1 ─ %1 = Base.broadcasted(Main.f, Main.x)
│ %2 = Base.materialize(%1)
└── return %2
tkf
February 27, 2020, 7:35am
5
Alternatively:
julia> Meta.@lower f.(x)
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.broadcasted(f, x)
│ %2 = Base.materialize(%1)
└── return %2
))))
broadcast(f, x) needs to return an array if x is an array. If f.(g.(x)) is lowered to broadcast(f, broadcast(g, x)), it would need to create intermediate array. Instead, julia does
julia> Meta.@lower f.(g.(x))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.broadcasted(g, x)
│ %2 = Base.broadcasted(f, %1)
│ %3 = Base.materialize(%2)
└── return %3
))))
If you read the manual you’d notice that broadcasted (note ed) does not do the actual computation. Rather, the actual computation is done in materialize without creating any intermediate arrays.
It’s actually broadcast(f, ) that calls (the lowered version of) f.():
julia> string.(("one","two","three","four"), ": ", 1:4)
4-element Array{String,1}:
"one: 1"
"two: 2"
"three: 3"
"four: 4"
```
"""
broadcast(f::Tf, As...) where {Tf} = materialize(broadcasted(f, As...))
# special cases defined for performance
@inline broadcast(f, x::Number...) = f(x...)
@inline broadcast(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) where {N} = map(f, t, ts...)
"""
broadcast!(f, dest, As...)
Like [`broadcast`](@ref), but store the result of
`broadcast(f, As...)` in the `dest` array.