# Writing Type Stable Loops

**URL:** https://discourse.julialang.org/t/writing-type-stable-loops/69705
**Category:** Performance
**Tags:** question, loops, type-stability
**Created:** [October 13, 2021, 5:35pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705 "2021-10-13T17:35:57Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![dleather](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dleather/32/43762_2.png) [@dleather](https://discourse.julialang.org/u/dleather)
#### Post date: [October 13, 2021, 5:35pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/1 "2021-10-13T17:35:57Z")

</div>

For /While loops create a local scope. Thus, if you’d like to write a function the outputs variables defined inside of the for /while loop, one must declare these variables as global beforehand, or use a let wrapper.

The contradiction I see is that Julia has a hard time compiling code with global variables. I’ve seen this in my own code as I try to achieve type stability.

My questions are:

- How can I write loops in a way that is type stable, even though I must declare globals?
- Will declaring a global variable outside of a for loop have a significant impact on the performance of my code?

---

<div class="post-metadata">

### Author: ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)
#### Post date: [October 13, 2021, 5:38pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/2 "2021-10-13T17:38:01Z")

</div>

The easiest way to do this is by writing a function, for loops should be inside functions, and you can either create the variable inside the function, or make a mutating function that takes a variable.

---

<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: [October 13, 2021, 5:38pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/3 "2021-10-13T17:38:39Z")

</div>

You should not use globals at all, write everything inside functions:

```julia
function myloop(y)
     x = 0
     for i in 1:10
          x += i*y
     end
     return x
end

```

no need for declaring anything global. And you pass the parameters required to that function.

An additional comment: In Julia a good advice for newcommers is _never_, _ever_, use the `global` keyword. If you feel that you cannot avoid using it, ask for advice.

---

<div class="post-metadata">

### Author: ![dleather](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dleather/32/43762_2.png) [@dleather](https://discourse.julialang.org/u/dleather)
#### Post date: [October 13, 2021, 5:48pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/4 "2021-10-13T17:48:53Z")

</div>

I think the structure of my code makes this a little more tricky. Here is sample code written for legibility (I’m new, so sorry if its inefficient style). Note that each function call is type stable.

```julia
function myloop(x_mat)
    trig = 0
    cnt = 1
    T_step = 100
    tol = 1e-6
    global Q
    global x
    global ν
    global s
    global T_bar
    while trig ==0
        x_in = x_mat[:,1:T_step*cnt]
        x,ν,s = simulate_data(x_in)
        Q = compute_Q(x,ν,s)

        if Q[end]<tol
            trig = 1
            T_bar = T_step*cnt
        else
            cnt += 1
        end

    end

    return Q, x, ν, s, T_bar
end

```

---

<div class="post-metadata">

### Author: ![dleather](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dleather/32/43762_2.png) [@dleather](https://discourse.julialang.org/u/dleather)
#### Post date: [October 13, 2021, 5:51pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/5 "2021-10-13T17:51:06Z")

</div>

Thanks! Please see post above.

---

<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: [October 13, 2021, 5:52pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/6 "2021-10-13T17:52:13Z")

</div>

Pass all those “global” variables as parameters to your function. For example with a named tuple:

```julia
julia> function f(x_mat,p)
           Q, x = p.Q, p.x # In 1.7 you can write this as (; Q, x) = p
           x_mat = x_mat*Q + x
           return x_mat
       end
f (generic function with 1 method)

julia> p = (Q = 1.0, x = 2.0); x_mat = 2.0;

julia> f(x_mat,p)
4.0

```

---

<div class="post-metadata">

### Author: ![dleather](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dleather/32/43762_2.png) [@dleather](https://discourse.julialang.org/u/dleather)
#### Post date: [October 13, 2021, 5:55pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/7 "2021-10-13T17:55:24Z")

</div>

Is it ok if they are empty? For example:

```julia
p = (Q = Matrix{Float64}, x = Float64)

```

---

<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: [October 13, 2021, 5:58pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/8 "2021-10-13T17:58:50Z")

</div>

An empty matrix is defined with `Q = Matrix{Float64}(undef,5,5)` for example. There is no such thing as an empty `scalar`, like a single Float64.

What exactly are you trying to do in this case?

---

<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: [October 13, 2021, 6:02pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/9 "2021-10-13T18:02:38Z")

</div>

> [@dleather](#):
>
> `x,ν,s = simulate_data(x_in)`

Note that here, if `x`, `v` and `s` are immutable (meaning, they are not arrays), declaring them “global” or not is the same, you are just redefining them again here.

Maybe your question is of another sort: How to use the value of a variable that was created inside a loop, outside the scope of the loop. Then, there are two options: initialize the value with any value outside the loop, or declare it `local` (I prefer this one):

```julia
julia> function myloop()
           local m
           for i in 1:2
               m = i
           end
           return m
       end
myloop (generic function with 1 method)

julia> myloop()
2

julia> function myloop()
           m = 0 
           for i in 1:2
               m = i
           end
           return m
       end
myloop (generic function with 1 method)

julia> myloop()
2

```

Looking at your code there, I think is what you actually want, to declare all those variales as `local` to the scope of the function, to use the values they acquire in the loop and return them.

---

<div class="post-metadata">

### Author: ![dleather](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dleather/32/43762_2.png) [@dleather](https://discourse.julialang.org/u/dleather)
#### Post date: [October 13, 2021, 6:44pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/10 "2021-10-13T18:44:21Z")

</div>

> [@lmiq](#):
>
> Maybe your question is of another sort: How to use the value of a variable that was created inside a loop, outside the scope of the loop. Then, there are two options: initialize the value with any value outside the loop, or declare it `local` (I prefer this one):

Yes! Thank you so much for working through my ill-posed questions, and getting at the heart of the matter. This is what I was looking for, as x, v, s are all arrays.

---

<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: [October 13, 2021, 6:49pm UTC](https://discourse.julialang.org/t/writing-type-stable-loops/69705/11 "2021-10-13T18:49:20Z")

</div>

> [@dleather](#):
>
> This is what I was looking for, as x, v, s are all arrays.

Nice, next step is to realize that you are allocating new arrays at every iteration of the loop, as the result of your `simulate` function. This will be somewhat slow. The same for `Q`, and for `x_in`. Ideally you want to allocate the arrays outside the loop and make those function mutate their values.
