Constant type but changing value

Is it possible to create a constant type but changing value variable? For example, I would like to create a max variable and a call to a function increments the max value and returns the new max. The max variable needs to be global so new calls to the function from different places return the right value. You can’t do this with const since the value of the constant is fixed in the function. If you do it with a regular variable, the type instability makes it slower. My workaround is to create an array but that seems less than ideal

Constant values don’t work

const maxVal3 = 10

function inc3()
    return global maxVal3 += 1
end 
julia> inc3()
WARNING: redefining constant maxVal3
11

julia> inc3()
11

julia> inc3()
11

Global regular variables are slower

maxVal = 10

function inc()
    return global maxVal += 1
end

julia> @btime inc()
  18.832 ns (1 allocation: 16 bytes)
500514

Array is my current workaround

const maxVal2 = [10]

function inc2()
    push!(maxVal2, pop!(maxVal2) + 1)
    return maxVal2[1]
end

julia> @btime inc2()
  10.280 ns (0 allocations: 0 bytes)
500517

Don’t use a global variable, just pass in the current value and return the new value.

You can use a Ref, which behaves like a very lightweight zero-dimensional array holding a single value.

3 Likes

@dpsanders Unfortunately, based on the setup of the code, that is not possible

@rdeits Can you show a quick example of that? I was looking at those but couldn’t figure it out

const maxVal = Ref(10)

function inc()
    return maxVal[] += 1
end
5 Likes

Another possibility is to define your own callable type.

Assuming that the existing code which calls the maxval-updating function is something like

function foo(n)
   for i=1:n 
      inc3()
   end
end

Define a type which holds the maxval, and overload the call operator:

mutable struct Inc3
   maxval::Int  # adjust the data type as necessary
end

@inline function (f::Inc3)()
   f.maxval+=1
   nothing
end

Instantiate it at the beginning of your program:

const inc3 = Inc3(10)  # initializing the maxval to 10

This lets you run the inc3-using code with good performance:

@btime foo(1)
  1.557 ns (0 allocations: 0 bytes)

and you can access the resulting maximum via inc3.maxval.

3 Likes