Despite being equal, they behave differently:
julia> sqrt.([4, 9])
2-element Vector{Float64}:
2.0
3.0
julia> sqrt == √
true
julia> √.([4, 9])
ERROR: syntax: invalid identifier name "."
Stacktrace:
[1] top-level scope
@ none:1
Despite being equal, they behave differently:
julia> sqrt.([4, 9])
2-element Vector{Float64}:
2.0
3.0
julia> sqrt == √
true
julia> √.([4, 9])
ERROR: syntax: invalid identifier name "."
Stacktrace:
[1] top-level scope
@ none:1
This is just a parsing thing. You want
julia> (√).([4, 9])
2-element Vector{Float64}:
2.0
3.0
Then where can I read Julia’s parsing implementation? I looked around in julia/src/ast.c but I’m not familiar with this part of code and can not find the precise location which is in cause.
I couldn’t tell you the cause either. But I do know that for unary or binary operators, to broadcast them you generally need to wrap them in parentheses.
The actual parser is here: julia/julia-parser.scm at master · JuliaLang/julia · GitHub
Yeah, strangely with infix operators the .
goes in front of the operator:
julia> .√([4, 9])
2-element Vector{Float64}:
2.0
3.0
It’s like the binary .+
and .*
. That said, given that this is a syntax error… I wonder if we couldn’t support either placement.
I think the ship has sailed on that. After 1.6, .+
and .*
are defined as Base.Broadcast.BroadcastFunction(+)
. Actually so is square root
julia> .√
Base.Broadcast.BroadcastFunction(sqrt)
I don’t see why that changes anything. .√([3,4])
doesn’t actually create a BroadcastFunction
. I’m just saying maybe we could also support √.([3,4])
like a normal function named √
?
Just to be clear, the reason they behave differently is that sqrt
is an ordinary function name while √
is a unary operator.
That means, for example, that you can apply √
without parentheses:
julia> √2
1.4142135623730951
and like all operators in Julia it is “vectorized” by putting a .
before the operator (a convention adopted from Matlab):
julia> .√[4,9]
2-element Vector{Float64}:
2.0
3.0
I agree with @mbauman that, if you use a binary/unary operator OP
with parens, as OP(...)
, then it would not be crazy to allow OP.(...)
as an alternative vectorization syntax similar to ordinary functions. This doesn’t seem like it would be breaking since it is currently a syntax error.