Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia's @. macro and binary operators

Tags:

julia

For all I know, the following should be equivalent:

julia> rand(2).^2
2-element Array{Float64,1}:
 0.164246
 0.47107 

julia> @. rand(2)^2
ERROR: DimensionMismatch("Cannot multiply two vectors")
Stacktrace:
 [1] power_by_squaring(::Array{Float64,1}, ::Int64) at ./intfuncs.jl:169
 [2] broadcast(::##65#66) at ./sysimg.jl:86

Same goes for this one:

julia> 1./rand(2)
2-element Array{Float64,1}:
 1.93886
 3.01834

julia> @. 1/rand(2)
ERROR: MethodError: no method matching /(::Int64, ::Array{Float64,1})
Closest candidates are:
  /(::PyCall.PyObject, ::Any) at /home/simon/.julia/v0.6/PyCall/src/pyoperators.jl:11
  /(::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, ::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) at int.jl:38
  /(::Union{Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}, ::BigInt) at gmp.jl:381
  ...
Stacktrace:
 [1] broadcast(::##69#70) at ./sysimg.jl:86

What the heck am I doing wrong?

like image 455
gTcV Avatar asked Jan 03 '23 21:01

gTcV


1 Answers

help?> @.

@. expr

Convert every function call or operator in expr into a "dot call" (e.g. convert f(x) to f.(x)), and convert every assignment in expr to a "dot assignment" (e.g. convert += to .+=).

If you want to avoid adding dots for selected function calls in expr, splice those function calls in with $.

For example, @. sqrt(abs($sort(x))) is equivalent to sqrt.(abs.(sort(x))) (no dot for sort).

The problem is that this way you are also broadcasting rand, the @. macro works on all function calls including binary operators calls (ie. 1 + 1 is parsed as +(1, 1))

  1. Use the @macroexpand macro in order to see the resulting expression from a macro invocation.

  2. Interpolate the function calls ($(f(x))) that you don't want to broadcast with @..

julia> @macroexpand @. rand(2)^2
:(^.(rand.(2), 2))    # same as: rand.(2).^2

julia> eval(ans)
ERROR: DimensionMismatch("Cannot multiply two vectors")

julia> @macroexpand @. $(rand(2))^2
:(^.(rand(2), 2))  # same as: rand(2).^2

julia> eval(ans)
2-element Array{Float64,1}:
 0.26266
 0.326033

julia> @macroexpand @. 1 / rand(2)
:(/.(1, rand.(2)))    # same as: 1 ./ rand.(2)

julia> eval(ans)
ERROR: MethodError: no method matching /(::Int64, ::Array{Float64,1})

julia> @macroexpand @. 1 / $(rand(2))
:(/.(1, rand(2)))    # same as: 1 ./ rand(2)

julia> eval(ans)
2-element Array{Float64,1}:
 37.1023
  1.08004
like image 61
HarmonicaMuse Avatar answered Jan 22 '23 02:01

HarmonicaMuse