# @. macro for element-wise operations and array slicing

**URL:** <https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761>\
**Category:** General Usage\
**Created:** [September 7, 2017, 2:13pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761 "2017-09-07T14:13:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ckoe-bccms](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckoe-bccms/32/1816_2.png) [@ckoe-bccms](https://discourse.julialang.org/u/ckoe-bccms)\
**Post date:** [September 7, 2017, 2:13pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/1 "2017-09-07T14:13:29Z")

</div>

Hello everybody,

I have a larger expression involving purely element-wise operations on vector elements. Using functions like abs(), log10() requires the use of dot-syntax in julia 0.6 unless one ignores the depreciation warning you get when using the program non-interactively, i.e. I will have to use for example  
log10.(abs.(vector)). At this point I would like to use the @. macro instead of explicitely writing these dots .

According to [More Dots: Syntactic Loop Fusion in Julia](https://julialang.org/blog/2017/01/moredots) the @. macro should be equivalent to explicit dots. Only that it is not in connection with using length() as demonstrated in a brief made up example below ( I suspect this is a more general issue):

```julia
julia> abs.(x[1:Int64(round(length(x)/2.0))])
2-element Array{Float64,1}:
 1.0
 2.0
julia> @. abs(x[1:Int64(round(length(x)/2.0))])
ERROR: MethodError: no method matching colon(::Int64, ::Array{Int64,1})
Closest candidates are:
  colon(::T<:Real, ::Any, ::T<:Real) where T<:Real at range.jl:47
  colon(::A<:Real, ::Any, ::C<:Real) where {A<:Real, C<:Real} at range.jl:14
  colon(::T, ::Any, ::T) where T at range.jl:46
  ...

```

Naturally two questions arrive:

1. Is this non-equivalence a feature, a bug, a missing feature or am I using it wrong ? If I am using it wrong how should I use it ?
2. length(x)/2 is not automatically cast to integer as for example in matlab as far as I have observed. I apparently have to convert it explicitely with Int64(round(length(x)/2.0)) ? This looks as if I am doing something stupid. Is there a better way to do this ?

And no, I do not like to use throw-away-variables to do a

```julia
julia> lastindex=Int64(round(length(x)/2.0))
2

julia> @. abs(x[1:lastindex])
2-element Array{Float64,1}:
 1.0
 2.0

```

and clutter my code.

Thank you very much for your help in advance !

Best Regards

Christof

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [September 7, 2017, 2:37pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/2 "2017-09-07T14:37:30Z")

</div>

Actually, the blog post is exactly right: adding `@.` in front of an expression is equivalent to changing _all_ function calls from `f(x)` to `f.(x)`. That’s actually what’s happening and it’s what’s causing your error. The reason is that you want `length(x)` to operate on the array `x` and return a scalar length. But by adding `@.` out front, you’ve turned that into `length.(x)` which returns an array consisting of the length of each element of `x`. That’s exactly what `@.` is supposed to do, but it’s just not what you want in this case. The error comes because what ends up being evaluated is `1:Int64.(round.(length.(x) ./ 2.0)))` and Julia doesn’t have a method for a range from an integer to a vector.

Splitting out `lastindex` is a perfectly good solution (and has no performance penalty at all), as is just manually adding dots only where appropriate rather than using `@.`. Which one you pick is, of course, up to you.

As for (2), dividing two integers (or an integer and a float as you’re doing) _always_ produces a float. Because of that, you can just divide by `2` and not `2.0` and you will still get the correct answer (unlike python2). Unlike Matlab, Julia doesn’t allow you to index into an array with a float, so yes, rounding and converting to Int is necessary. If you don’t like the nested function calls, you can also do `round(Int, length(x) / 2))`.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [September 7, 2017, 2:38pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/3 "2017-09-07T14:38:52Z")

</div>

The `@.` macro adds dots to _all_ function calls in the expression. That is,

```julia
julia> @macroexpand @. abs(x[1:Int64(round(length(x)/2.0))])
:(abs.(x[1:Int64.(round.(/.(length.(x), 2.0)))]))

```

So if you want to use the `@.` macro, you’ll need to separate out the components that operate on the vector as a whole (like `length` here — you don’t want the length of every element in this case).

```julia
julia> n = Int64(round(length(x)/2.0))
       @macroexpand @. abs(x[1:n])
:(abs.(x[1:n]))

julia> @. abs(x[1:n])
2-element Array{Float64,1}:
 1.0
 2.0

```

As far as division, yes, you need to be explicit in how you want to convert the result to an index. In many cases, you can use the `÷` infix operator to do integer division, but that behaves differently from `round` — it truncates instead. You can also round directly to `Int` with `round(Int, length(x)/2)`. Or similarly with `ceil` or `floor`. Unfortunately there’s not a “one true way” that everyone always wants, so we have chosen not to do this automatically.

(As an aside, in this particular instance, you can also use the special `end` keyword to represent the last index in the collection: `@. abs(x[1:end÷2])`).

---

<div class="post-metadata">

**Author:** ![mdavezac](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdavezac/32/1472_2.png) [@mdavezac](https://discourse.julialang.org/u/mdavezac)\
**Post date:** [September 7, 2017, 2:42pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/4 "2017-09-07T14:42:31Z")

</div>

If you do `@macroexpand` on your expression, you find:

```nohighlight
julia> @macroexpand @. a[1:round(Int64, length(a) / 2)]
:(a[1:round.(Int64, /.(length.(a), 2))])

```

So `@.` is also applied to `length`: the expression becomes `a[1:[1, 1, 1, 1, 1]]`.

You might want to try instead

```nohighlight
@. abs(x[1:round(Int64, end/2))

```

Also, `round(Int64, x)` is indeed necessary, since `/` promotes two integers to floating points (If I understand it right)

---

<div class="post-metadata">

**Author:** ![ckoe-bccms](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckoe-bccms/32/1816_2.png) [@ckoe-bccms](https://discourse.julialang.org/u/ckoe-bccms)\
**Post date:** [September 7, 2017, 3:29pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/5 "2017-09-07T15:29:58Z")

</div>

Hello,

thank you very much for your answers !

Indeed I missed the emphasis on the word “every” which is in the online documentation of the macro.

Apparently this would work too without the need to introduce a throw-away-variable

```julia
2-element Array{Float64,1}:
 1.0
 4.0

```

which is of course simple once I understood the emphasis on “every” in the documentation. Not used to macros I guess, there must be of course limits on the complexity of transforms it can do.

With respect to the indexing:

```julia
round(Int64, end/2)

```

using “end” as a value is sure much nicer than what I have been doing. But I still will have to get used to it.

@mbauman: That would be the same as div(length(x),2) as fasr as I can see ? I am not sure how I would enter that infix operator, is that using UTF-8 I assume ?

Thank you very much again !

Best Regards

Christof

---

<div class="post-metadata">

**Author:** ![ckoe-bccms](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckoe-bccms/32/1816_2.png) [@ckoe-bccms](https://discourse.julialang.org/u/ckoe-bccms)\
**Post date:** [September 7, 2017, 3:31pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/6 "2017-09-07T15:31:20Z")

</div>

Sorry, copy and paste , it should have been

```julia
julia> @. abs(x[1:Int64(round($length(x)/2.0))])^2
2-element Array{Float64,1}:
 1.0
 4.0

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [September 7, 2017, 3:37pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/7 "2017-09-07T15:37:44Z")

</div>

> [@ckoe-bccms](#):
>
> @mbauman: That would be the same as div(length(x),2) as fasr as I can see ? I am not sure how I would enter that infix operator, is that using UTF-8 I assume ?

Yes, exactly. You can ask Julia how to enter it by copy/pasting it into a `?` help prompt:

```julia
help?> ÷
"÷" can be typed by \div<tab>

search: ÷ .÷

  div(x, y)
  ÷(x, y)

  The quotient from Euclidean division. Computes x/y, truncated to an integer.

```

---

<div class="post-metadata">

**Author:** ![ckoe-bccms](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ckoe-bccms/32/1816_2.png) [@ckoe-bccms](https://discourse.julialang.org/u/ckoe-bccms)\
**Post date:** [September 7, 2017, 10:32pm UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/8 "2017-09-07T22:32:22Z")

</div>

Hello,

that is of course nicely documented and might make code more readable.

I will probably stick to div(), though, as I would have to find out how to for example search for it in vim without copy&paste of the character (among other things). I remain a bit sceptical of using UTF-8 characters I do not have on my keyboard 🙂 Of course all of this has been discussed elsewhere, so I would like to just thank you again for your help.

Best Regards

Christof

---

<div class="post-metadata">

**Author:** ![mdavezac](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdavezac/32/1472_2.png) [@mdavezac](https://discourse.julialang.org/u/mdavezac)\
**Post date:** [September 8, 2017, 9:22am UTC](https://discourse.julialang.org/t/macro-for-element-wise-operations-and-array-slicing/5761/9 "2017-09-08T09:22:47Z")

</div>

If you are using vim without [juliavim](https://github.com/JuliaEditorSupport/julia-vim) you are missing out on, well, automatic latex to unicode. But that’s getting a bit off topic!
