# How to update an array efficiently

**URL:** https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727
**Category:** General Usage
**Created:** [September 13, 2019, 5:09pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727 "2019-09-13T17:09:09Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)
#### Post date: [September 13, 2019, 5:09pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/1 "2019-09-13T17:09:09Z")

</div>

Hello,

I found I use statements like this a lot:

```julia
A = func(A)

```

with  
`func` a function returning a array of the same size.

Is this efficient? Or there is a better way to write this kind of things?

Thanks.

---

<div class="post-metadata">

### Author: ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)
#### Post date: [September 13, 2019, 5:16pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/2 "2019-09-13T17:16:09Z")

</div>

if type of `A` changed, please use `let A = func(A)` to _update symbol_ for better performance.

Also, if original A is not used any more and you want a same-length and same-type array with specific initial value, use `fill!` and no need to assign here.

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [September 13, 2019, 5:34pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/3 "2019-09-13T17:34:34Z")

</div>

> [@thautwarm](#):
>
> if type of `A` changed, please use `let A = func(A)` to _update symbol_ for better performance.

There is no need for this anymore.

> [@linwaytin](#):
>
> Is this efficient? Or there is a better way to write this kind of things?

It is just as effective as `B = func(A)`. If you want to reuse the memory of `A` you need to update it in place, in Juila functions like that conventionally end with an exclamation mark, e.g.

```julia
function func!(A)
    # modify A
end

A = ... # initialize
func!(A)
func!(A) # reuse memory of A
```

---

<div class="post-metadata">

### Author: ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)
#### Post date: [September 13, 2019, 5:49pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/4 "2019-09-13T17:49:30Z")

</div>

> [@kristoffer.carlsson](#):
>
> > if type of `A` changed, please use `let A = func(A)` to _update symbol_ for better performance.
> 
> There is no need for this anymore.

Incredible. If it also applys when `A` is a free variable shared to others, I think this optimization is very advanced and cool.

---

<div class="post-metadata">

### Author: ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)
#### Post date: [September 13, 2019, 5:55pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/5 "2019-09-13T17:55:48Z")

</div>

Thank you.  
I use Python to do numerical computation.  
Trying to learn Julia, I found some basics are quite different.  
So this may be stupid question.

If I define a function like

```julia
function func!(a)
    # change a 
end

```

and call `func!(A)`, then if `A` is an array, the values in `A` get changed.  
But if `A` is just a variable, the value is not changed.

Is that right?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [September 13, 2019, 6:39pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/6 "2019-09-13T18:39:43Z")

</div>

First, there’s no distinction between A “is an array” vs A “is just a variable”.

If you call `func!(A)` and you mutate `A`, the change will be reflected in the `A` in the caller.

If you call `func!(A)` and you assigned to `A` in `func!`, the change will not be reflected in the caller.

This is exactly the same as python.

---

<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 13, 2019, 7:18pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/7 "2019-09-13T19:18:57Z")

</div>

Here’s an example showing how Julia’s behavior is exactly the same as Python’s when it comes to assignment vs. mutation:

Python:

```python
In [1]: def f(x):
   ...: x = [1, 2, 3]
   ...:     

In [2]: x = [0, 0, 0]

In [3]: f(x)

In [4]: x
Out[4]: [0, 0, 0]

In [5]: def g(x):
   ...: x[0] = 1
   ...: x[1] = 2
   ...: x[2] = 3
   ...:     

In [6]: g(x)

In [7]: x
Out[7]: [1, 2, 3]

```

Julia:

```julia
julia> function f(x)
         x = [1, 2, 3]
       end
f (generic function with 1 method)

julia> x = [0, 0, 0]
3-element Array{Int64,1}:
 0
 0
 0

julia> f(x)
3-element Array{Int64,1}:
 1
 2
 3

julia> x
3-element Array{Int64,1}:
 0
 0
 0                                                                                                                                                               
                                                                                                                                                                 
julia> function g(x)
         x[1] = 1
         x[2] = 2
         x[3] = 3
       end
g (generic function with 1 method)                                                                                                                               
                                                                                                                                                                 
julia> g(x)
3                                                                                                                                                                
                                                                                                                                                                 
julia> x
3-element Array{Int64,1}:
 1
 2
 3

```

In both languages, the function `f(x)` assigns a new value to the name `x` within the function. This has no effect on the value `x` which was passed in. The function `g(x)`, on the other hand, actually mutates the value, and we can see that mutation in the value `x` which was passed in.

As @yuyichao said, this has nothing to do with the fact that `x` is an array, and is only affected by the difference between assigning a new value vs. mutating an existing value.

---

<div class="post-metadata">

### Author: ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)
#### Post date: [September 14, 2019, 11:47pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/8 "2019-09-14T23:47:25Z")

</div>

The above replies by @yuyichao and @rdeits have already given you a good explanation of what happens in each case. Here is a concrete example to answer your question directly.

```julia
julia> function func(A)
           B = sin.(A ./ 3)
       end
func (generic function with 1 method)

julia> function func!(A)
           @. A = sin(A / 3)
       end
func! (generic function with 1 method)

julia> using BenchmarkTools

julia> @btime func($A);
  5.428 ms (2 allocations: 7.63 MiB)

julia> @btime func!($A);
  2.761 ms (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)
#### Post date: [September 15, 2019, 2:21am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/9 "2019-09-15T02:21:23Z")

</div>

Thank you for all the clarification.  
Now I know the difference between assignment and mutation.

Can I ask what ` @. A = sin(A / 3)` means?

Thank you.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [September 15, 2019, 2:44am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/10 "2019-09-15T02:44:20Z")

</div>

`@.` is a macro which replaces every function with an element-wise version of the function. So this replaces every element of the stay with the sin of 1/3rd of the element.

---

<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 15, 2019, 2:57am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/11 "2019-09-15T02:57:55Z")

</div>

See [More Dots: Syntactic Loop Fusion in Julia](https://julialang.org/blog/2017/01/moredots) for more on `@.` and broadcasting.

---

<div class="post-metadata">

### Author: ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)
#### Post date: [September 15, 2019, 3:06am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/12 "2019-09-15T03:06:16Z")

</div>

Is it equivalent to `A .= sin.(A ./ 3)` and thus is a mutation instead of assignment?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [September 15, 2019, 3:22am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/13 "2019-09-15T03:22:23Z")

</div>

Yes

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [September 15, 2019, 5:37am UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/14 "2019-09-15T05:37:11Z")

</div>

If you ever wonder what a macro is doing, two approaches can help.  
The first is typing `?` in the repl, to enter help mode.

```julia
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

```

This works for anything that someone wrote documentation for. That includes most things in Base Julia and many libraries (including the standard libraries). For example:

```julia
julia> using LinearAlgebra

help?> mul!
search: mul! rmul! lmul! accumulate! muladd vmul vmuladd widemul accumulate module Module mutable struct @ __MODULE__ baremodule parentmodule NamedTuple isimmutable promote_rule SegmentationFault

  mul!(Y, A, B) -> Y

  Calculates the matrix-matrix or matrix-vector product AB and stores the result in Y, overwriting the existing value of Y. Note that Y must not be aliased with either A or B.

```

For macros specifically, there is also the helpful macro `@macroexpand`:

```julia
julia> @macroexpand @. A = sin(A / 3)
:(A .= sin.((/).(A, 3)))

```

Which expands any macros so you can see what they’re doing to the code. It’ll expand all macros in the expression that follows.

```julia
julia> @macroexpand @time @. A = sin(A / 3)
quote
    #= util.jl:158 =#
    local var"#7#stats" = Base.gc_num()
    #= util.jl:159 =#
    local var"#9#elapsedtime" = Base.time_ns()
    #= util.jl:160 =#
    local var"#8#val" = (A .= sin.((/).(A, 3)))
    #= util.jl:161 =#
    var"#9#elapsedtime" = Base.time_ns() - var"#9#elapsedtime"
    #= util.jl:162 =#
    local var"#10#diff" = Base.GC_Diff(Base.gc_num(), var"#7#stats")
    #= util.jl:163 =#
    Base.time_print(var"#9#elapsedtime", (var"#10#diff").allocd, (var"#10#diff").total_time, Base.gc_alloc_count(var"#10#diff"))
    #= util.jl:165 =#
    Base.println()
    #= util.jl:166 =#
    var"#8#val"
end

```

In case you find this hard to read, the library `MacroTools` has (among many other useful tools) the function `prettify`, which makes them much more readable:

```julia
julia> using MacroTools

julia> prettify(@macroexpand @time @. A = sin(A / 3))
quote
    local tapir = Base.gc_num()
    local camel = Base.time_ns()
    local guanaco = (A .= sin.((/).(A, 3)))
    camel = Base.time_ns() - camel
    local hippopotamus = Base.GC_Diff(Base.gc_num(), tapir)
    Base.time_print(camel, hippopotamus.allocd, hippopotamus.total_time, Base.gc_alloc_count(hippopotamus))
    Base.println()
    guanaco
end

```

---

<div class="post-metadata">

### Author: ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)
#### Post date: [September 15, 2019, 8:30pm UTC](https://discourse.julialang.org/t/how-to-update-an-array-efficiently/28727/15 "2019-09-15T20:30:53Z")

</div>

Thanks for all replies. They are very helpful.  
Julia has an excellent community.
