How to lock the variable type in Julia?

Viewed 148

I want to lock the type of a variable in Julia, how to do? For example, I define an array called weight,

weight = Array{Float64,1}([1,2,3])

Now I want to lock the type of weight as Array{Float64,1}, is it possible?

I mean if do not lock the type of weight, then if I mistakenly or casually do

weight = 1

Then weight will become an Int64 variable, so it is not longer a 1D array. This is obviously not what I want.

I just want to make sure that once I defined weight as 1D Float64 array, then if I change the type of weight, I want Julia gives me an error saying that the type of weight has been changed which is not allowed. Is it possible? Thanks!

This is useful because by doing this, it may preventing me from forgetting weight is an 1D array, and therefore preventing bugs.

2 Answers

For global variables use const:

julia> const weight = Array{Float64,1}([1,2,3])
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> weight[1]=11
11

julia> weight=99
ERROR: invalid redefinition of constant weight

Note that redefining the reference will throw a warning:

julia> const u = 5
5

julia> u=11
WARNING: redefinition of constant u. This may fail, cause incorrect answers, or produce other errors

You can circumvent it by using the Ref type:

julia> const z = Ref{Int}(5)
Base.RefValue{Int64}(5)

julia> z[] = 11
11

julia> z[] = "hello"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64

In functions use local with type declaration:

julia> function f()
           local a::Int
           a="hello"
       end;

julia> f()
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64

You'd normally write:

weight::Vector{Float64} = Array{Float64,1}([1,2,3])

...but this doesn't seem to be possible in global scope:

julia> weight::Vector{Float64} = Array{Float64,1}([1,2,3])
ERROR: syntax: type declarations on global variables are not yet supported
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

However, you can do it in local scope or in a struct:

julia> function fun()
        weight::Vector{Float64} = Array{Float64,1}([1,2,3])
        weight = 1
       end
fun (generic function with 1 method)

julia> fun()
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Vector{Float64}
Closest candidates are:
  convert(::Type{T}, ::AbstractArray) where T<:Array at array.jl:532
  convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/factorization.jl:58
  convert(::Type{T}, ::T) where T<:AbstractArray at abstractarray.jl:14
  ...
Stacktrace:
 [1] fun()
   @ Main ./REPL[10]:3
 [2] top-level scope
   @ REPL[11]:1

You could use const, but then redefinition with a value of the same type will cause a warning:

julia> const weight = Array{Float64,1}([1,2,3]);

julia> weight = [2.]
WARNING: redefinition of constant weight. This may fail, cause incorrect answers, or produce other errors.
1-element Vector{Float64}:
 2.0
Related