# Calculus with in place functions

**URL:** https://discourse.julialang.org/t/calculus-with-in-place-functions/28546
**Category:** New to Julia
**Tags:** question
**Created:** [September 8, 2019, 8:59pm UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546 "2019-09-08T20:59:10Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![MatFi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matfi/32/10002_2.png) [@MatFi](https://discourse.julialang.org/u/MatFi)
#### Post date: [September 8, 2019, 8:59pm UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/1 "2019-09-08T20:59:10Z")

</div>

I want to understand how in place functions are treatet when used like in this example

```julia
function g!(u)
      u[:] .= 2*u[:] 
end

u=[1]

julia > g!(u) .*(u .+ g!(u))
1-element Array{Int64,1}:
 32

```

For my understanding, this is a completely awkward result. It seems, that the functions `g` are evaluated first, independent of associative/commutative properties. I’m the only one having problems with that or is this common knowledge/general rule  
(I just asking, because it took weeks for me to recognize that such behavior might show up. )

**EDIT:** For all newcomers digging this out. Writing this as

```julia
function g!(u)
      u .= 2 .* u 
end

```

is allocation free and therefore much more performant as DNF pointed out:

> [@DNF](#):
>
> The slicing causes allocations to happen

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 9, 2019, 5:21am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/2 "2019-09-09T05:21:49Z")

</div>

> [@MatFi](#):
>
> It seems, that the functions `g` are evaluated first

Using prefix notation (and ignoring broadcasting for now) you have

```julia
*(g(u), +(u, g(u)))

```

so I wonder how you imagine that anything but the `g`s could be evaluated first — they are needed as inputs for both `+` and `*`.

> [@MatFi](#):
>
> independent of associative/commutative properties

I don’t know what you mean here. If you are thinking about [precedence](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1), that plays no role here as your expression is fully parenthesized.

> [@MatFi](#):
>
> it took weeks for me to recognize that such behavior might show up

Generally, it is best to be more careful about mutating functions, or at least [signal it with a `!`](https://docs.julialang.org/en/v1/manual/style-guide/#Append-!-to-names-of-functions-that-modify-their-arguments-1). If you must use in-place operations, don’t mix them with other complex expressions. Julia is just doing what you asked for here.

---

<div class="post-metadata">

### Author: ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)
#### Post date: [September 9, 2019, 5:32am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/3 "2019-09-09T05:32:48Z")

</div>

Argument-mutating functions do what they say. Hence it is not possible to use them in these kinds of expressions. Period, I’m afraid. BTW: Your function should also indicate its argument-mutating property by its name, `g!`.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [September 9, 2019, 5:55am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/4 "2019-09-09T05:55:49Z")

</div>

> [@Tamas\_Papp](#):
>
> Using prefix notation (and ignoring broadcasting for now) you have
> 
> ```julia
> *(g(u), +(u, g(u)))
> 
> ```
> 
> so I wonder how you imagine that anything but the `g` s could be evaluated first — they are needed as inputs for both `+` and `*` .

Actually it’s easy to imagine that everything is evaluated starting from the deepest nested brackets. Namely, first `g(u)`, then `+(u, g(u))`, then another `g(u)`, and then the final multiplication. I’m not saying this is better (or worse) than evaluating `g(u)` twice and only after that computing the `+` and `*` operations, just pointing at another option.

---

<div class="post-metadata">

### Author: ![MatFi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matfi/32/10002_2.png) [@MatFi](https://discourse.julialang.org/u/MatFi)
#### Post date: [September 9, 2019, 7:10am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/5 "2019-09-09T07:10:20Z")

</div>

> [@aplavin](#):
>
> first `g(u)` , then `+(u, g(u))` , then another `g(u)` , and then the final multiplication.

Jep…  
this is how i would have expected it:

```julia-auto
function g!(u)
      u[:] .= 2*u[:] 
end

u=[1]
a=u .+ g!(u)
b= g!(u) .* a

julia> b
1-element Array{Int64,1}:
 16

```

Just to clarify. In principal i don’t care how this is handled as soon as I know. How ever for newcomers this is far from beeing clear IMHO.

> [@Tamas\_Papp](#):
>
> Generally, it is best to be more careful about mutating functions, or at least [signal it with a `!`](https://docs.julialang.org/en/v1/manual/style-guide/#Append-!-to-names-of-functions-that-modify-their-arguments-1)

> [@PetrKryslUCSD](#):
>
> Your function should also indicate its argument-mutating property by its name, `g!` .

True usually I do, just forgot when i wrote the example. I will change the example accordingly, thanks

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 9, 2019, 8:11am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/6 "2019-09-09T08:11:22Z")

</div>

> [@aplavin](#):
>
> Actually it’s easy to imagine that everything is evaluated starting from the deepest nested brackets.

I thought it is pretty well-defined, with the evaluation order being left-to-right, but I could not just find this in the manual.

---

<div class="post-metadata">

### Author: ![MatFi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matfi/32/10002_2.png) [@MatFi](https://discourse.julialang.org/u/MatFi)
#### Post date: [September 9, 2019, 8:39am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/7 "2019-09-09T08:39:11Z")

</div>

> [@Tamas\_Papp](#):
>
> I thought it is pretty well-defined, with the evaluation order being left-to-right,

Yes this is why I ask. because as I see it, this statement is not truly consistent with:

```julia
 u=[1];u .+ u .+ g!(u)
1-element Array{Int64,1}:
 6

julia> u=[1];u .+ u .+ g!(u) .+g!(u)
1-element Array{Int64,1}:
 16

```

A simple left to right in case of `u=[1];u .+ u .+ g!(u) ` should lead to `[4]`. But Julia in any case computes every `g!` first.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 9, 2019, 8:58am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/8 "2019-09-09T08:58:16Z")

</div>

I think this is because Julia uses a single `+` call with multiple arguments here, eg

```julia
julia> ex = :(a + b + c)
:(a + b + c)

julia> ex.head
:call

julia> ex.args
4-element Array{Any,1}:
 :+
 :a
 :b
 :c

```

I said above, I think it is bad style to depend on these things. IMO having to think about precedence and evaluation order in mutating code is a code smell.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [September 9, 2019, 9:10am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/9 "2019-09-09T09:10:30Z")

</div>

> [@MatFi](#):
>
> ```julia
> function g!(u)
> u[:] .= 2*u[:]
> end
> 
> ```

This is an aside to the main point of this discussion, but this implementation ruins the point of in-place mutation, which is normally avoiding allocations. The slicing causes allocations to happen. Observe:

```julia
using BenchmarkTools

foo!(x) = (x[:] .= 2*x[:])
bar!(x) = (x .= 2*x)
baz!(x) = (x .= 2 .* x)

julia> @btime foo!(x) setup=(x=rand(1000)); # your implementation
  1.298 μs (3 allocations: 15.92 KiB)

julia> @btime bar!(x) setup=(x=rand(1000));
  709.508 ns (1 allocation: 7.94 KiB)

julia> @btime baz!(x) setup=(x=rand(1000));
  97.624 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![MatFi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matfi/32/10002_2.png) [@MatFi](https://discourse.julialang.org/u/MatFi)
#### Post date: [September 9, 2019, 9:22am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/10 "2019-09-09T09:22:09Z")

</div>

> [@Tamas\_Papp](#):
>
> I said above, I think it is bad style to depend on these things. IMO having to think about precedence and evaluation order in mutating code is a code smell.

I completely agree but let me explain why I brought this up  
When i want to solve a DAE with DifferentialEquations.jl, I can do this either in from of an `ODEProblem ` using a `mass_matrix =M` which solves `M*du = f!(du,u)`.  
Or, as i thought, I can translate it to an `DAEProblem` via ` 0 = f!(du,u) .- M*du` . And this failed since i was not aware of this kind of interference. So I necessarily need to allocate at least one time more to rewrite my problem.

But in summary I have no questions left thanks a lot for your patience 👍

> [@DNF](#):
>
> The slicing causes allocations to happen

Jea, next time i will spent more time in providing a 100% acceptable, performant and still minimal, example ( but true, the one i gave was on of the worst possible )

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [September 9, 2019, 9:24am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/11 "2019-09-09T09:24:51Z")

</div>

> [@MatFi](#):
>
> Jea, next time i will spent more time in providing a 100% acceptable, performant and still minimal, example ( but true, the one i gave was on of the worst possible )

It wasn’t intended as a criticism—the example was fine for illustrating the question—but as information to help you improve your code. I assumed that you weren’t aware of this performance trap.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 9, 2019, 9:25am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/12 "2019-09-09T09:25:59Z")

</div>

> [@MatFi](#):
>
> So I necessarily need to allocate at least one time more to rewrite my problem.

I am not sure, it would be helpful to see the original problem.

Generally, if the whole calculation can be captured in an elementwise update function `f`, then

```julia
a .= f.(a, b, c)

```

should work.

---

<div class="post-metadata">

### Author: ![MatFi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matfi/32/10002_2.png) [@MatFi](https://discourse.julialang.org/u/MatFi)
#### Post date: [September 9, 2019, 9:29am UTC](https://discourse.julialang.org/t/calculus-with-in-place-functions/28546/13 "2019-09-09T09:29:47Z")

</div>

> [@Tamas\_Papp](#):
>
> a .= f.(a, b, c)

Indeed , good point…

> [@DNF](#):
>
> It wasn’t intended as a criticism

I didn’t understand it as such either. 😀
