朱莉娅的@.宏和二元运算符

gTc*_*TcV 3 julia

据我所知,以下内容应该是等效的:

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
Run Code Online (Sandbox Code Playgroud)

同样适合这个:

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
Run Code Online (Sandbox Code Playgroud)

我到底做错了什么?

Sal*_*apa 6

帮忙?> @.

@.EXPR

将expr中的每个函数调用或运算符转换为"点调用" (例如转换f(x)f.(x)),并将expr中的每个赋值转换为"点分配"(例如转换+=.+=).

如果要避免在expr中为选定的函数调用添加点,请将这些函数调用与之拼接$.

例如,@. sqrt(abs($sort(x)))相当于sqrt.(abs.(sort(x)))(没有用于排序的点).

问题是这样你也在广播rand,@.宏工作在所有函数调用上,包括二元运算符调用(即被1 + 1解析为+(1, 1))

  1. 使用@macroexpand宏以便从宏调用中查看生成的表达式.

  2. 插入$(f(x))您不想广播的函数调用()@..

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
Run Code Online (Sandbox Code Playgroud)

  • 一个很好的解释.我认为值得补充的是,问题是例如`exp.(rand.(2))`失败,因为它相当于`broadcast(x-> exp(rand(x)),2)`,并且这种表示很明显,这段代码会引发错误. (2认同)