# Functionality like the SAVE statement in Fortran?

**URL:** <https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268>\
**Category:** General Usage\
**Tags:** fortran, functions\
**Created:** [March 23, 2025, 2:43am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268 "2025-03-23T02:43:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![leespen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leespen1/32/221928_2.png) [@leespen1](https://discourse.julialang.org/u/leespen1)\
**Post date:** [March 23, 2025, 2:43am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/1 "2025-03-23T02:43:46Z")

</div>

I am converting some Fortran code to Julia, and I noticed the fortran code uses the SAVE statement ([SAVE (FORTRAN 77 Language Reference)](https://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vnb7/index.html)).

I have very little experience in Fortran, but it seems like this statement allows a variable to be preserved across function calls.

I can see how this kind of statement could be dangerous (especially in a multithreaded environment), but I think it is very useful in the context in which it is used, which is to save an initial guess for which interval a number is in (e.g. Given non-decreasing numbers t\_1 \< t\_2 \< t\_3 \dots, if t\_i \< t \< t\_{i+1} then return i. Since the function (subroutine, in Fortran terms) is called many times with t only increasing slightly each call, it saves a lot of time to have the last interval used and use it as an initial guess for the next call, since most of the time the initial guess is correct.

This could also be accomplished by making the initial guess an argument to the function, but that can be burdensome when the function call is nested deeply in many other function calls, since I have to add an argument to each of the functions in the call stack. Moreover, the more “direct” the translation between Julia and Fortran, the easier the translation becomes.

Does the same functionality as Fortran’s SAVE statement exist in Julia? Is there a language feature that lets me save a variable _to the function_?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 23, 2025, 2:55am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/2 "2025-03-23T02:55:59Z")

</div>

Does it work like the “static” keyword in C?

No, I don’t think Julia has it. But I think the same effect can be achieved with a closure.

---

<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:** [March 23, 2025, 3:04am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/3 "2025-03-23T03:04:51Z")

</div>

What’s the difference between this and a global variable? Also, how would you want this to work with multiple dispatch?

---

<div class="post-metadata">

**Author:** ![leespen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leespen1/32/221928_2.png) [@leespen1](https://discourse.julialang.org/u/leespen1)\
**Post date:** [March 23, 2025, 3:14am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/4 "2025-03-23T03:14:03Z")

</div>

Somehow I wasn’t aware of the “static” keyword in C, but yes, it looks like it works the same way.

I’m also not familiar with closures. The Julia docs description of them doesn’t tell me a whole lot ([Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured)), and given the example they give I don’t see how to apply a closure here.

Could you please give an example of how an effect like I described could be achieved? For example, how can I use a closure to implement an initial guess for `i` in the following function:

```julia
"""
`ts` is assumed to be a strictly increasing vector of floats.
`t` is assumed to be greater than `ts[1]` and less than `ts[end]`
"""
function find_interval(t::Float64, ts::Vector{Float64})
  i = 1
  while !(ts[i] < t < ts[i+1])
    if t > ts[i+1]
      i += 1
    else
      i -= 1
    end
  end
  return i
end
  

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 23, 2025, 3:14am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/5 "2025-03-23T03:14:13Z")

</div>

> [@Oscar\_Smith](#):
>
> What’s the difference between this and a global variable

A static variable in C is not visible outside of the function where it is defined.

---

<div class="post-metadata">

**Author:** ![leespen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leespen1/32/221928_2.png) [@leespen1](https://discourse.julialang.org/u/leespen1)\
**Post date:** [March 23, 2025, 3:18am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/6 "2025-03-23T03:18:55Z")

</div>

What @ufechner7 said. A global variable could achieve the functionality I asked for, but on the other hand I don’t like that the variable could be changed by something other than the function, and I also don’t like that it would pollute the namespace of the module.

As for multiple dispatch, I don’t know. In my case, the variable I want to save is always an `Int64`.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 23, 2025, 3:21am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/7 "2025-03-23T03:21:24Z")

</div>

Simple example of a closure:

```julia
function create_counter()
    count = 0
    return function()
        count += 1
        return count
    end
end

counter = create_counter()

```

Perhaps like this (untested)?

```julia
function find_interval(t::Float64, ts::Vector{Float64})
  i = 1
  return function result(t::Float64, ts::Vector{Float64})
    while !(ts[i] < t < ts[i+1])
      if t > ts[i+1]
        i += 1
      else
        i -= 1
      end
    end
  end
end

```

---

<div class="post-metadata">

**Author:** ![leespen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leespen1/32/221928_2.png) [@leespen1](https://discourse.julialang.org/u/leespen1)\
**Post date:** [March 23, 2025, 3:53am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/8 "2025-03-23T03:53:51Z")

</div>

Thanks, that works great! I hadn’t considered using a variable outside the scope of the inner-defined function.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 23, 2025, 4:31am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/9 "2025-03-23T04:31:19Z")

</div>

> [@ufechner7](#):
>
> ```julia
> function create_counter()
> count = 0
> return function()
> count += 1
> return count
> end
> end
> 
> counter = create_counter()
> 
> ```

If performance is important, this must be rewritten to use a `Ref` wrapper:

```julia
function create_counter()
    count = Ref(0)
    return function()
        c = count[] += 1
        return c
    end
end

counter = create_counter()

```

Otherwise, you’re subject to the infamous closure boxing issue. (See [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276) or just search this forum—reading material for days!)

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 23, 2025, 10:10am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/10 "2025-03-23T10:10:44Z")

</div>

Closures aren’t the only way to make function-external data that doesn’t occupy the global namespace.

> **Yet another (unboxed) closure capturing a local variable**
>
> ```julia
> julia> function makecountedcall() # closure, Ref for unboxed capture
> callcounter = Ref(0)
> function countedcall()
> callcounter[] += 1
> println(callcounter)
> end
> end
> makecountedcall (generic function with 1 method)
> 
> julia> makecountedcall() # parameter shows unboxed capture
> (::var"#countedcall#6"{Base.RefValue{Int64}}) (generic function with 1 method)
> 
> julia> makecountedcall().callcounter # internal captured variable
> Base.RefValue{Int64}(0)
> 
> ```

> **A \`local\`-declared variable inside a top-level \`begin\` block**
>
> ```julia
> julia> begin
> local callcounter2 = Ref(0)
> function countedcall2()
> callcounter2[] += 1
> println(callcounter2)
> end
> end
> countedcall2 (generic function with 1 method)
> 
> julia> countedcall2()
> Base.RefValue{Int64}(1)
> 
> julia> countedcall2()
> Base.RefValue{Int64}(2)
> 
> julia> callcounter2
> ERROR: UndefVarError: `callcounter2` not defined in `Main`
> 
> ```

> **A \`global\`-declared method definition inside a local \`let\` block**
>
> ```julia
> julia> let
> callcounter3 = Ref(0)
> global function countedcall3()
> callcounter3[] += 1
> println(callcounter3)
> end
> end
> countedcall3 (generic function with 1 method)
> 
> julia> countedcall3()
> Base.RefValue{Int64}(1)
> 
> julia> countedcall3()
> Base.RefValue{Int64}(2)
> 
> julia> callcounter3
> ERROR: UndefVarError: `callcounter3` not defined in `Main`
> 
> ```

> **Interpolate and assign a specific \`RefValue\` instance into a globally scoped method definition**
>
> ```julia
> julia> @eval function countedcall4()
> callcounter4 = $(Ref(0))
> callcounter4[] += 1
> println(callcounter4)
> end
> countedcall4 (generic function with 1 method)
> 
> julia> countedcall4()
> Base.RefValue{Int64}(1)
> 
> julia> countedcall4()
> Base.RefValue{Int64}(2)
> 
> julia> callcounter4
> ERROR: UndefVarError: `callcounter4` not defined in `Main`
> 
> ```

For consistent demonstration, I made all of the external data `RefValue{Int}`. As stated before, the manual `Ref` wrapper isn’t necessary for the closure to operate, but it does help performance by evading the automatic and poorly inferred `Core.Box`. `Meta.@lower` and `@code_warntype` also show the same applies to the `begin`-`local` and `let`-`global` examples. `Ref` is necessary for the interpolated example; you can think of it as a non-existent global `const` variable, no automatic boxing there.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [March 23, 2025, 10:21am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/11 "2025-03-23T10:21:01Z")

</div>

> [@leespen1](#):
>
> This could also be accomplished by making the initial guess an argument to the function, but that can be burdensome when the function call is nested deeply in many other function calls, since I have to add an argument to each of the functions in the call stack.

IMHO it’s worth the burden in the long term if the code is not a fast quick and dirty experiment. Passing an explicit **state** to your mutating (!) computation functions will make your code more readable and potentially amenable to thread safety in the future.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 23, 2025, 4:03pm UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/12 "2025-03-23T16:03:24Z")

</div>

To complete this list:

- Replace the function with a callable struct

```julia-repl
julia> mutable struct CallCounter
           count::Int
           CallCounter() = new(0)
       end

julia> function (c::CallCounter)()
           c.count += 1
           println(c.count)
       end

julia> callcounter = CallCounter()
CallCounter(0)

julia> callcounter()
1

julia> callcounter()
2

julia> callcounter
CallCounter(2)

```

---

<div class="post-metadata">

**Author:** ![leespen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leespen1/32/221928_2.png) [@leespen1](https://discourse.julialang.org/u/leespen1)\
**Post date:** [March 23, 2025, 7:11pm UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/13 "2025-03-23T19:11:40Z")

</div>

I agree on safety, but I’m not so sure about readability. As a _developer_ it is more maintainable, but for a _user_ it may be confusing/cumbersome.

I used the interval finding as an example, but my actual use case is that I want to evaluate bsplines at a certain point, which (in the fortran code), has an interval finding subroutine. So the value I actually want to return is the sum of all the bspline basis functions at a certain point. The interval index is not the main thing I am interested in.

If the user wants to evaluate the bsplines multiple times in succession while using good guesses for the interval index, the user has to handle the output of both a the bspline value and the updated initial guess. This puts more of a burden on the user. Providing a default method for when an initial guess is not supplied would reduce the burden on the user, but they would not get the benefit of having a good initial guess that is updated each function call.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 24, 2025, 12:32am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/14 "2025-03-24T00:32:06Z")

</div>

> [@leespen1](#):
>
> the user has to handle the output of both a the bspline value and the updated initial guess. This puts more of a burden on the user. Providing a default method for when an initial guess is not supplied would reduce the burden on the user

I think you’re implying you know so already, but you can do both. Closures and callable struct instances differ from static memory in that the state can be instantiated several times independently without replacing the method; in Julia, the callable is also an input to the call and thus involved in method dispatch as much as the arguments. For example, the user can easily get to ufechner7’s `create_counter` or danielwe’s `CallCounter`, even if not deemed API. My `begin`-`local`, `let`-`global`, and `@eval ... $()...` examples on the other hand require replacement of the method to re-instantiate the state because the method itself is referencing an instance without an intermediary global variable, and there’s no way to make several independent states for the same method.

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [March 24, 2025, 12:52am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/15 "2025-03-24T00:52:22Z")

</div>

Is this Thread safe? Can you use it in multi-threaded situation?

```julia
function create_counter_func()
    count = Ref(0)
    return function()
        c = count[] += 1
        return c
    end
end

counter_func = create_counter_func()

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 24, 2025, 6:37am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/16 "2025-03-24T06:37:14Z")

</div>

No. `count[] += 1` expands to `count[] = count[] + 1`, which is not atomic; the read and write are separate operations. You may get data races if you call the same instance `counter_func` from multiple concurrent tasks. In multithreading/multitasking contexts you need atomics or locks.

The easiest way I know to make this thread-safe is to use `Threads.Atomic` as follows, but do note that this is a deprecated API:

```julia
function create_counter_func()
    count = Threads.Atomic{Int}(0)
    return function()
        c_old = Threads.atomic_add!(count, 1)
        # atomic_add! returns the old value;
        # add 1 to get the desired return value
        return c_old + 1
    end
end

```

It’s probably better to learn how to use the newer `@atomic` API, in which case I think it’s going to be easier to start from the `CallCounter` callable struct.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [March 24, 2025, 6:46am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/17 "2025-03-24T06:46:49Z")

</div>

One can try to reduce the effort of the user by providing a default state for the first call. What about the following toy example. where `g` is a solver that may be efficiently accelerated by providing some state `s`(e.g. last solution) when available (not at the first call):

```julia
julia> g(x,state) = (2x,state+1)
g (generic function with 2 methods)

julia> g(x) = (2x,1) #initial state is set to 1
g (generic function with 2 methods)

julia> (res,state) = g(1.2) #first call
(2.4, 1)

julia> (res,state) = g(1.2,state) #subsequent calls
(2.4, 2)

julia> (res,state) = g(1.2,state) #subsequent calls
(2.4, 3)

```

---

<div class="post-metadata">

**Author:** ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)\
**Post date:** [March 24, 2025, 7:25am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/18 "2025-03-24T07:25:25Z")

</div>

A while back I made the `Guesser` in FindFirstFunctions.jl for exactly the use case you described: [FindFirstFunctions.jl · FindFirstFunctions.jl](https://docs.sciml.ai/FindFirstFunctions/dev/#FindFirstFunctions.Guesser). That package also uses highly optimized algorithms to perform the search.

---

<div class="post-metadata">

**Author:** ![PatrickHaecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrickhaecker/32/222891_2.png) [@PatrickHaecker](https://discourse.julialang.org/u/PatrickHaecker)\
**Post date:** [March 24, 2025, 10:09am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/19 "2025-03-24T10:09:03Z")

</div>

Thanks for this list and the addition of @danielwe . As this occurs so often, wouldn’t it be worth to put this list in the documentation? Somewhere below [Noteworthy differences from C/C++](https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-C/C) probably in its own section `Julia ⇔ C/C++: Static Variables`

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [March 24, 2025, 11:02am UTC](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268/20 "2025-03-24T11:02:19Z")

</div>

> [@danielwe](#):
>
> The easiest way I know to make this thread-safe is to use `Threads.Atomic` as follows, but do note that this is a deprecated API:
> 
> ```julia
> function create_counter_func()
> count = Threads.Atomic{Int}(0)
> return function()
> c_old = Threads.atomic_add!(count, 1)
> # atomic_add! returns the old value;
> # add 1 to get the desired return value
> return c_old + 1
> end
> end
> 
> ```
> 
> It’s probably better to learn how to use the newer `@atomic` API, in which case I think it’s going to be easier to start from the `CallCounter` callable struct.

The new way would be

```julia
mutable struct AtomicRef{T} <: Ref{T}
    @atomic x::T
    AtomicRef{T}() where {T} = new{T}()
    AtomicRef(x::T) where {T} = new{T}(x)
    AtomicRef{T}(x) where {T} = new{T}(convert(T, x))
end

function create_counter_func()
    count = AtomicRef(0)
    () -> @atomic count.x += 1
end

```

I have no idea why the above `AtomicRef` or something similar isn’t provided by `Base`.

I’ve had to recreate it a couple times in different places so far.

* * *

**EDIT** : As pointed out below, the original code written above was incorrect. I have edited it to combine the load and store into one atomic op.

[Next page](https://discourse.julialang.org/t/functionality-like-the-save-statement-in-fortran/127268.md?page=2)
