Dot syntax

I can’t see why these three statements do different things:

data = [4;3;2;1;5]

x = data .- findmin(data)[1] # Subtract the min from each value. Does what I want.
x = @. data - findmin(data)[1] # Error, can't broadcast because it "sees" an array of length 2???
x = @. data - getindex(findmin(data),1). # Works but doesn't produce the desired result.

I feel like all three lines should do the same thing: subtract the minimum value from each number in the array?

@. makes all functions broadcasted. In other words, @. data - findmin(data)[1] becomes:

data .- findmin.(data)[1]

You don’t want to broadcast findmin and apply it separately to each element. If you write the indexing as a function call, it’ll also broadcast getindex over that result.

7 Likes

Thanks. So this particular example isn’t a good candidate for @.

Don’t you mean minimum(data)?

3 Likes

You can opt-out of the dotting for particular function calls with $, e.g.

x = @. data - $findmin(data)[1]

(This is explained in the @. documentation.)

9 Likes

Related, when using @., is there a way to opt out of the dotting within parentheses?

For example, for scalars α, β, and a vector x, I would like to perform (α * β) .* x. using @. I thought I would prevent the penetration of the dot into the parenthesized expression by @. $(α * β) * x, but it seems that both @. (α * β) * x and @. $(α * β) * x generate the same native code according to @code_native, so I’m confused.

That works. Code native isn’t really where you should be checking this sort of thing — you’re almost surely not looking at what you think you’re looking at.

julia> Meta.@macroexpand @. (α * β) * x
:((*).((*).(α, β), x))

julia> Meta.@macroexpand @. $(α * β) * x
:((*).(α * β, x))
3 Likes