Strange behavior, when constant is redefined inside a function


#21

I just fell into the same trap as @DrKrar.
For my simulation I need to read few performance critical parameters from a file once in the beginning which will be constant throughout the simulation. I intended to use consts for that, since the docs stated that only changing the type of a const raises an error and the meaning of the warning was somewhat vague. I have outlined two potential strategies I could use:

“Dirty” way with warnings

module A
  "prominent documentation for x"
  const x = dummy
  export x
  function init()
    global const x=readonce() #sets actual value, causes warnings
    ...
  end
end
module B
  import A: x # selective imports are great
  ...do something with x...
end

Correct way:

module A
  function init()
    "this will not generate documentation for x ?!"
    global const x = readonce()
  end
end
module B
  using A: x # UndefVarError, if A.init() not called yet
  ...
end
module C
  using A # works
  ...
end

The correct way of course works (except for the documentation not being generated, bug or feature?), but reduces the readability of the code. I’d like to have important variables defined at a prominent position instead of popping up in the middle of some function. Is there any preferred way to deal with such situations?


#22

What’s wrong with


module A

function read_constant()
    ...
end

const x = read_constant()

end

If for some reason you can’t initialize at module load time, consider a memoized function with no arguments, or a vector with a single element that you later initialize, etc.


#23
julia> const dummy = Ref(0)
Base.RefValue{Int64}(0)

julia> function init()
           dummy[] = 3
       end
init (generic function with 1 method)

julia> init()
3

julia> dummy[]
3

#24

Thanks for the help. I have thought of similar solutions as well, but was a little reluctant to use arrays due to performance. Some background: The consts are sizes of some multidimensional tensors I’m doing some heavy numbercrunching on, so I want to make sure both type and value are known later for having fancy compiler optimizations.
Since constants are cached, should there in theory be a difference in performance in whether I just use the constant directly in a function or dispatch onto the value of it (especially for @kristoffer.carlsson suggestion)?

const x=3
function A(data)
  for i=1:x 
    ...   
  end
end
function B(data, ::Val(X)) where X
  for i=1:X
    ...
  end
end
res = B(data,Val(x))

#25

Benchmark it.


#26

@code_llvm tells me that using the consts results in identical code as dispatching on the value of the variable, which is pretty nice.