var::MyType the variable keeps MyType as type and can't change further on

Hey community,

I know that Julia is dynamic and variables can change type. But would it be nice to have a way of restricting that?

My ideas is:

var::Int64 = 10
var = 10.0 # throws an error 
var2 = 10
var2 = 10.0 # no error here

That works in local scopes. There is an issue to make it work in global scope, but the dev work needs to be done. It’s been a low priority issue since 2014.

3 Likes

That’s precisely how const var = 10 automatically behaves. Oh there’s something printed out if you change it to another Int but who reads warnings anyways. It works.

(Seriously, though, that’s why this has been such low priority — const covers a large swatch of potential use-cases. And conversely, const isn’t available in local scopes but type constants are!)

4 Likes

That said, const really shouldn’t work that way (and isn’t guaranteed to). Also functions that use the const value already don’t work sometimes depending on what the compiler chooses to do.

2 Likes

This is also a really big annoyance for metaprogramming.

1 Like

I’d also take issue with the ‘automatically behaves’ part. It does exactly what the warning says if that’s what you’d qualify as behaving.

julia> const a = 1
1

julia> f(x) = a*x + 1
f (generic function with 1 method)

julia> f(1)
2
julia> const a = typemax(Int)
WARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.
9223372036854775807

julia> f(1)
2
1 Like

Apparently I need to be more obvious with my tongue-in-cheek sarcasm. Sorry about that. Key point was simply that const covers a subset of the use-cases for this functionality. As the warning states, I would highly dissuade you from using it for real mutable work. A decent combination/workaround here is a const Ref.

1 Like
julia> let
           var::Int = 1
           var = 1.
       end
1.0

julia> let
           var::Int = 1
           var = 1.1
       end
ERROR: InexactError: Int64(1.1)
Stacktrace:
 [1] Int64 at .\float.jl:710 [inlined]
 [2] convert(::Type{Int64}, ::Float64) at .\number.jl:7
 [3] top-level scope at REPL[9]:3

julia> let
           var::Int = 1
           var = 1.
           var
       end
1

That’s cool and should help static linting. But

julia> function f(i::Int)
           i = 1
           i = 1.
           i
       end
f (generic function with 1 method)

julia> f(1)
1.0

The type assertions in method arguments are just for dispatch and many would feel it’d be annoying if they blocked you from changing the type of an argument later on in the body. One thing you could do is make a let block inside the function (perhaps even automate this with a macro?)

julia> function f(i::Int)
           let i::Int = i
               i = 1.0
               i
           end
       end
               
f (generic function with 1 method)

julia> f(1)
1

or skip the let entirely:

julia> function f(i::Int)
           i::Int = i
           i = 1.0
           i
       end
f (generic function with 1 method)

julia> f(1)
1
2 Likes