在Julia编程语言中,符号“@”代表什么意思?

8
例如,在这里:
ys = lift(frequency, phase) do fr, ph
    @. 0.3 * sin(fr * xs - ph)
end

来自这里


我无法将其解释为一个宏定义或调用

2个回答

6

TLDR: @ 调用宏。https://docs.julialang.org/en/v1/manual/metaprogramming/

在我看来,Julia 的最佳特性之一就是其宏。它们允许您轻松编写操作源代码的函数。例如,@.0.3 * sin(fr * xs - ph) 转换为 0.3 .* sin(fr .* xs - ph)。另一个常见的例子是 @time,它大致将相同的表达式转换为

t1=time()
0.3 * sin(fr * xs - ph)
println(time()-t1)


请注意,这两种情况都无法通过函数实现,因为函数在运行之前会对其输入进行评估,而宏则是直接操作代码本身。

5

我认为值得补充的是,通过调用帮助命令可以很容易地学习@.的作用。按下?键然后键入@.并按回车键即可获得以下信息:

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).

  (@. is equivalent to a call to @__dot__.)

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> x = 1.0:3.0; y = similar(x);
  
  julia> @. y = x + 3 * sin(x)
  3-element Array{Float64,1}:
   3.5244129544236893
   4.727892280477045
   3.4233600241796016

在这里,你还会学到@.只是@__dot__的简写。

如果你想找到它的定义,可以写例如:

julia> @which @. 1
@__dot__(__source__::LineNumberNode, __module__::Module, x) in Base.Broadcast at broadcast.jl:1241

要获得其实现位置的确切信息,或者写下@edit @. 1,它将在您的编辑器中打开。

上面我已经解释了如何学习@.的作用和实现方式。如果你想学习@.(或者任何宏)的效果,你可以使用@macroexpand宏。因此,如果你写入:

julia> @macroexpand @. coalesce(sin(@view x[:, 1]), 0.0)
:(coalesce.(sin.(true && (view)(x, :, 1)), 0.0))

您可以看到@.宏如何重写您的原始表达式coalesce(sin(x), 0.0)。请注意,在这种情况下,表达式未被评估 - 您只会得到一个等价表达式,其中所有宏已被删除。

如果您只想查看@.宏展开(假设 - 如上面的示例中一样 - 它是最外层的宏),则使用:

julia> @macroexpand1 @. coalesce(sin(@view x[:, 1]), 0.0)
:(coalesce.(sin.(#= REPL[11]:1 =# @view(x[:, 1])), 0.0))

正如您所看到的,@macroexpand1不是递归的,仅展开最外层的宏,而保留了@view宏不受影响。

1
也许值得一提的是,@macroexpand1 也可以吗? - Frames Catherine White
好的 - 我会添加这个。实际上,我考虑过在注释中包含它,但我没有这样做是为了避免答案变得过于复杂 :)。 - Bogumił Kamiński

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接