Dims
Dims

Reputation: 51039

What does an 'at' @ sign mean in Julia?

For example, here:

ys = lift(frequency, phase) do fr, ph
    @. 0.3 * sin(fr * xs - ph)
end

from here.


I am failing to interpret it as a macro definition or call.

Upvotes: 12

Views: 1836

Answers (2)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69869

I think it is worth to add that it is easy to learn what @. does by invoking help. Press ? then write @. and hit enter to get:

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

where you also learn that @. is just a shorthand for @__dot__.

And if you want to find its definition write e.g.:

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

to get the exact information on location of its implementation or write @edit @. 1 and it will get opened-up in your editor.

Above I have commented on how to learn what @. does and how it is implemented. If you want to learn what is the effect of @. (or any macro in general) you can use the @macroexpand macro. Therefore if you write e.g.:

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

you can see how @. macro rewrites your original expression coalesce(sin(x), 0.0). Note that in this case the expressions are not evaluated - you only get an equivalent expression with all macros removed.

If you wanted to see only @. macro expanded (assuming - as in an example above it is the outermost macro) then use:

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

As you can see @macroexpand1 is not recursive and only expanded the outermost macro and left @view macro untouched.

Upvotes: 9

Oscar Smith
Oscar Smith

Reputation: 6388

TLDR: @ invokes a macro. https://docs.julialang.org/en/v1/manual/metaprogramming/

One of julia's best features in my opinion are it's macros. They allow you to easily write functions that manipulate source code. @. for example turns 0.3 * sin(fr * xs - ph) into 0.3 .* sin(fr .* xs - ph). Another common example is @time which roughly would translate the same expression to

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

Note that neither of these are achievable by a function, since functions have their inputs evaluated before they run, while macros instead operate on the code itself.

Upvotes: 7

Related Questions