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
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.
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!)
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.
This is also a really big annoyance for metaprogramming.
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
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
.
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