# Too many dots

**URL:** <https://discourse.julialang.org/t/too-many-dots/125293>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [January 28, 2025, 10:02am UTC](https://discourse.julialang.org/t/too-many-dots/125293 "2025-01-28T10:02:24Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![henrikjaerleblad](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrikjaerleblad/32/21172_2.png) [@henrikjaerleblad](https://discourse.julialang.org/u/henrikjaerleblad)\
**Post date:** [January 28, 2025, 10:02am UTC](https://discourse.julialang.org/t/too-many-dots/125293/1 "2025-01-28T10:02:24Z")

</div>

EDIT: In the original version of this post, I included the exact expression for computing the `jac` output. This allowed other users to run performance tests on dot vs scalar versions of the function. However, I realized that since the expression is based on mathematical equations that have yet to be published, the expression had to be replaced with `(EXPRESSION INVOLVING LOTS OF DOTS)`. Once the work has been published, I can re-include the exact expression and reference the published article.

Hi,

I have a colleague who has coded in Python before and is asking me for advice on a function he has written in Julia. He says that his Julia code, which utilizes the function, runs faster if the input arguments are not type specified. This I can understand. However, to achieve correct functionality, he has coded dot-operations everywhere. The function is:

```julia
using NaNMath

function his_function(γ_b, cosLAB, E_b, m_b, m_t, m_d, m_r, A, B, D)
    # We have to account for the sign in the quadratic solution, before differentiating
    s = -sign.(cos.(γ_b))

    jac = s .* (EXPRESSION INVOLVING LOTS OF DOTS)

    return jac
end

```

The input arguments to the function will always have the types:

```julia
his_function(γ_b::Vector{Float64}, cosLAB::Vector{Float64}, E_b::Vector{Float64}, m_b::Float64, m_t::Float64, m_d::Float64, m_r::Float64, A::Vector{Float64}, B::Vector{Float64}, D::Vector{Float64})

```

My question is simple. I think all the dots make the code look very Python-esque. How would you re-write the code to make it look better, and also run better? Or maybe I am misunderstanding something, and this is fine?

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [January 28, 2025, 10:15am UTC](https://discourse.julialang.org/t/too-many-dots/125293/2 "2025-01-28T10:15:29Z")

</div>

Perhaps the blog [More Dots: Syntactic Loop Fusion in Julia](https://julialang.org/blog/2017/01/moredots/) is useful. As mentioned in there, you can use [`@.`](https://docs.julialang.org/en/v1/base/arrays/#Base.Broadcast.@ __dot__ ) in front of the expression to dottify every function call.

If you don’t like broadcasting you can simply use a `for` loop.

---

<div class="post-metadata">

**Author:** ![lupemba](https://avatars.discourse-cdn.com/v4/letter/l/e5b9ba/32.png) [@lupemba](https://discourse.julialang.org/u/lupemba)\
**Post date:** [January 28, 2025, 10:23am UTC](https://discourse.julialang.org/t/too-many-dots/125293/3 "2025-01-28T10:23:51Z")

</div>

Another approach could be to just define the function for scalar values and then use the dot syntax to call it on vectors (or map or loops). This might affect performance but not in the same catastrophic way as in python.

```julia
his_function_scalar.(γ_b, cosLAB, E_b, m_b, m_t, m_d, m_r, A, B, D)

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 28, 2025, 11:56am UTC](https://discourse.julialang.org/t/too-many-dots/125293/4 "2025-01-28T11:56:05Z")

</div>

Clearly that are lot of terms repeated many times (for instance `(E_b .+ 2 * m_b)`). It likely that one can get a much more clear and faster code by splitting these calculations in a loop, like:

```julia
for i in eachindex(jac, E_b, m_b)
    eb2mb = E_b[i] + 2 * m_b[i]
    ...
    jac[i] = s[i] * eb2mb ...
end

```

If you put all arrays used inside the `eachindex(...)` call you safely add `@inbounds` to the for loop and, likely, achieve close to optimal performance.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 28, 2025, 12:25pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/5 "2025-01-28T12:25:01Z")

</div>

> [@lupemba](#):
>
> This might affect performance but not in the same catastrophic way as in python.

In fact, the **performance will probably get better** , because the line `s = -sign.(cos.(γ_b))` currently allocates two extra temporary arrays that are not needed (one for `s` and one because the unary `-` is not dotted). And there might be other dots that were missed, it’s hard to see by inspection.

In fact, I tried this and it got **2x faster** on my machine for 1000-element arrays:

```julia
julia> γ_b, cosLAB, E_b, m_b, m_t, m_d, m_r, A, B, D = [rand(1000) for i = 1:10];

julia> @btime his_function($γ_b, $cosLAB, $E_b, $m_b, $m_t, $m_d, $m_r, $A, $B, $D);
  58.144 μs (36 allocations: 94.50 KiB)

julia> @btime his_function_nodots.($γ_b, $cosLAB, $E_b, $m_b, $m_t, $m_d, $m_r, $A, $B, $D);
  28.615 μs (3 allocations: 7.88 KiB)

```

If you have a function that logically operates on scalars in Julia, like this one does, there is no reason in general to vectorize it. Just vectorize it when the function is called (if ever! you might also re-write the call site in terms of scalars).

One of the hardest habits to unlearn, coming from Python or Matlab or similar, is the distorted performance model that those languages teach you (“my code is slow, loops are slow, only vectorized library functions are fast”).

---

<div class="post-metadata">

**Author:** ![lupemba](https://avatars.discourse-cdn.com/v4/letter/l/e5b9ba/32.png) [@lupemba](https://discourse.julialang.org/u/lupemba)\
**Post date:** [January 28, 2025, 12:37pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/6 "2025-01-28T12:37:48Z")

</div>

Thanks for checking. After posting, I also remember some other advantage.  
It is also possible to call the scalar function on range and iterators without allocating the inputs and with `map!` it is also possible to manage when the output vector is allocated.

The main take away here is probably that scalar functions are good in Julia and there is no need to vectorize the internals of the function.

---

<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:** [January 28, 2025, 1:04pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/7 "2025-01-28T13:04:50Z")

</div>

Another advantage to making the function scalar and dotting only at the callsite, is that you can then trivially make it work in-place on a pre-allocated buffer, if you want:

```julia
jac .= his_function.(...)

```

---

<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:** [January 28, 2025, 1:47pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/8 "2025-01-28T13:47:03Z")

</div>

> [@henrikjaerleblad](#):
>
> However, I realized that since the expression is based on mathematical equations that have yet to be published, the expression had to be replaced with `(EXPRESSION INVOLVING LOTS OF DOTS)`

That’s a bit unfortunate. The old edit is still visible. Can a moderator remove or hide the old edit so the equation disappears? @stevengj?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 28, 2025, 2:00pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/9 "2025-01-28T14:00:01Z")

</div>

> [@lmiq](#):
>
> Clearly that are lot of terms repeated many times (for instance `(E_b .+ 2 * m_b)`).

The compiler should factor these out for you with common-subexpression elimination, at least for standard hardware numeric types.

The code might be clearer if you do it manually, of course.

(But you don’t want to do it manually in the original vectorized code because it will result in additional temporary arrays.)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 28, 2025, 2:04pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/10 "2025-01-28T14:04:33Z")

</div>

> [@henrikjaerleblad](#):
>
> However, I realized that since the expression is based on mathematical equations that have yet to be published

I don’t see what you are worried about. The equations are incomprehensible without explanation.

(Even if they weren’t, and were a remarkable advance that other people could understand and want to copy, unless you take years to publish it’s not likely that anyone will “scoop” you, and even more unlikely that they would do so without citing you. Lots of code gets published on open-source repositories long before any associated paper is published; I’m not aware of any case where this was a problem.)

Unless these incomprehensible equations are somehow a trade secret?

---

<div class="post-metadata">

**Author:** ![henrikjaerleblad](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrikjaerleblad/32/21172_2.png) [@henrikjaerleblad](https://discourse.julialang.org/u/henrikjaerleblad)\
**Post date:** [January 28, 2025, 2:13pm UTC](https://discourse.julialang.org/t/too-many-dots/125293/11 "2025-01-28T14:13:59Z")

</div>

True. My concern was merely due to me wishing to exercise good/correct scientific practice.
