@. and UndefVarError


#1

I have here a simple snippet of an example function that works just fine, i.e it returns what I expect it to return when i call it with a 2D argument x and a 1D argument p.

@. function dummy(x,p)
3.0*x[:,2] +p[1] +x[:,1]*p[2]
end

If instead i say (for example because i want to use the result of this calculation in the same function for further calculations)

@. function dummy(x,p)
w= 3.0*x[:,2] +p[1] +x[:,1]*p[2]
return w
end

then I get an “UndefVarError: w not defined”. so far so good.

however, i have tried all sorts of ways that I can think of defining w (as a local array of appropriate shape, i.e. an array of the length of the first dimension of x) but the error message remains always the same. even if i try to define w as an obviously wrong type, the error message is “not defined” as opposed to some form of “nonsense defined”

how do i define a local w correctly in julia for use in a @. function?

thanks


#2

You don’t need to apply @. to the entire function (and I wouldn’t recommend doing so, for exactly the reason you’ve run into here). The problem is that @. turns your = into .=, which in turn transforms w = ... into w .= ... which tries to broadcast the result into the (non-existent) array w.

Instead, just do:

function dummy(x, p)
  w = @.(3.0*x[:,2] +p[1] +x[:,1]*p[2])
  return w
end

Also, please quote your code so that it will render correctly.


#3

Not sure why, but the parser seems to be sensitive to a particular space here:

julia> x = randn(10,10); p = randn(10);
julia> @. 3.0*x[:,2] + p[1] + x[:,1] * p[2]
10-element Array{Float64,1}:
 -2.9666319136896138 
  2.7282891603028543 
 -4.853840108488322  
  0.6058019669739523 
 -1.2711187026514819 
  0.07949352735277701
  1.151771108029404  
  3.6311609306720025 
  1.156418356474127  
 -2.5863095768830022 

julia> @. 3.0*x[:,2] +p[1] + x[:,1] * p[2]
ERROR: LoadError: MethodError: no method matching @__dot__(::LineNumberNode, ::Module, ::Expr, ::Expr)
Closest candidates are:
  @__dot__(::LineNumberNode, ::Module, ::Any) at broadcast.jl:1145
in expression starting at REPL[24]:1

#4

It’s because macro argument parsing is a space sensitive parsing context, and the parser uses the space to disambiguate unary vs binary +. Compare:

julia> :(@a y +x).args[3:end]
2-element Array{Any,1}:
 :y   
 :(+x)

julia> :(@a y + x).args[3:end]
1-element Array{Any,1}:
 :(y + x)

Some kind of space sensitive disambiguation is more obviously necessary when you consider unary -.