# How to re-define a variable completely?

**URL:** <https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322>\
**Category:** New to Julia\
**Tags:** type\
**Created:** [June 14, 2023, 9:37am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322 "2023-06-14T09:37:30Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2023, 9:20pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/21 "2023-06-14T21:20:18Z")

</div>

yeah that’s pretty easy to do:

```julia
using ExprTools

macro stable_argtypes(fdef)
    d = splitdef(fdef)
    args = get!(d, :args, [])
    arg_asserts = Expr(:block)
    foreach(args) do arg
        if Base.isexpr(arg, :(::), 2)
            name, type = arg.args
            push!(arg_asserts.args, :($name :: $type = $name))
        end
    end
    old_body = get!(d, :body, Expr(:block))
    d[:body] = Expr(:block, arg_asserts, old_body)
    esc(combinedef(d))
end

```

and now

```julia
julia> @stable_argtypes function f(x::Int)
           x += 1.5
           x
       end
f (generic function with 1 method)

julia> f(1)
ERROR: InexactError: Int64(2.5)
Stacktrace:
 [1] Int64
   @ ./float.jl:900 [inlined]
 [2] convert
   @ ./number.jl:7 [inlined]
 [3] f
   @ ./REPL[5]:2 [inlined]
 [4] f(x::Int64)
   @ Main ./none:0
 [5] top-level scope
   @ REPL[6]:1

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 14, 2023, 9:24pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/22 "2023-06-14T21:24:06Z")

</div>

EDIT: IGNORE THE ANSWER BELOW, I HAVE MISUNDERSTOOD WHAT THE MANUAL MEANT.

This is kinda specific behaviour that comes from [`Base.convert`](https://docs.julialang.org/en/v1/base/base/#Base.convert):

> If T is a AbstractFloat type, then it will return the closest value to x representable by T.

To be honest, I find quite unfortunate that `convert` (which is used by the language itself in some non-intuitive situations like this) works for abstract types. This shows that this trick can have cause the opposite of the desired effect, instead of helping the code to be type stable, it becomes type-unstable because the concrete type returned by `convert(AbstractFloat, x)` will depend on the value of `x`.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 14, 2023, 9:25pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/23 "2023-06-14T21:25:36Z")

</div>

Thank you very much! Unfortunately I have dabbled very little in actual macro writing and it would be hard for me to do it even if I see it is possible.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 14, 2023, 9:26pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/24 "2023-06-14T21:26:05Z")

</div>

> [@Lukas\_Hebing](#):
>
> It seems, that the variable type is stored in the REPL. How can I clear or redefine the type without restarting the kernel?

As said before, you can’t undo global variables like that. Interestingly, the variable is still technically undefined because it’s not assigned, even though it exists and has its type restricted:

```julia
julia> my_var::Int64 = 3.2
ERROR: InexactError: Int64(3.2)
...
julia> my_var
ERROR: UndefVarError: my_var not defined

julia> my_var = 1.5
ERROR: InexactError: Int64(1.5)
...

```

So your global scope is stuck with a weird variable, and now you have to kill the whole REPL…is what people would’ve said before v1.9. Now you can [change what module the REPL evals in](https://docs.julialang.org/en/v1/stdlib/REPL/#Changing-the-contextual-module-which-is-active-at-the-REPL), you’re no longer stuck in `Main`. I don’t do this often because I already have the habit of trying things out in throwaway functions and let blocks for local scope behavior, and I still think that’s much better than bailing on a global scope. But if you want to switch out of Main and don’t want to reload all the other modules when you reimport them, this is how you can do it. Just have to be aware that if those modules were defined in `Main` then you will still have to import them from Main.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 14, 2023, 9:31pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/25 "2023-06-14T21:31:33Z")

</div>

> [@Henrique\_Becker](#):
>
> This shows that this trick can have cause the opposite of the desired effect, instead of helping the code to be type stable, it becomes type-unstable because the concrete type returned by `convert(AbstractFloat, x)` will depend on the value of `x`.

No, `convert(AbstractFloat, ::Int64)` is always a `Float64`, it doesn’t depend on the value of `x`.

IMO there’s nothing really wrong with @Benny’s example here. The user asked that the input type be `AbstractFloat`, so that implies any `AbstractFloat` should be fine to convert to.

Without the implicit `convert` steps, the resulting type of `x` would have ended up being `Int64` afterall.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 14, 2023, 11:15pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/26 "2023-06-14T23:15:00Z")

</div>

> [@DNF](#):
>
> > [@joa-quim](#):
> >
> > Honestly, I find it incomprehensible that we can impose that a variable has to dress with a certain cloth to enter that box (the function) but once inside it can change clothes to what ever it wants.
> 
> I look at it like this: The function signature `foo(x::Int)` is a filter on what type of _values_ (not variables) are accepted through the door. Once inside, the value is offered a jacket (“x”). This jacket does not belong to the value, and the jacket can be put on a different ‘guest’ (or on the back of a chair) at a later point.
> 
> Remember, when you pass a value to a function, referred to by a name, it generally changes name once through the door. If you call `foo(a)`, `a` becomes `x` once inside.

Sorry, had to leave and meanwhile lots of water passed under this bridge but let me still add that my vision is more like this. If that _value_ wants to change clothing at its own will, than it will have to enter naked. If it enters in uniform than it must keep it all time. This still looks pretty dynamic to me. That way we could have a:

```julia
function foo(x::police=empty_police_type, kw…)
	if isempty(x) && isa(var_in_kw, police) # Here ‘var_in_kw’ may very likely be a Any
		x = var_in_kw # Uf, got rid of that Any
	end
end

```

as it is, x will become a Any too. I do lots of parsing from values in a `Dict{:Symbol, Any}` and getting rid of those _Any’s_, even when I do know their true types, is a nightmare.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 14, 2023, 11:40pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/27 "2023-06-14T23:40:57Z")

</div>

> [@joa-quim](#):
>
> If that _value_ wants to change clothing at its own will, than it will have to enter naked. If it enters in uniform than it must keep it all time

Then how would multiple dispatch be implemented? I could very well need a `foo(x::Int)` method where `x` could be reassigned a floating point value, and I cannot refactor as a `foo(x::Real)` because that is already a separate method handling calls like `foo(1.5)`. Your design proposal isn’t crazy, it feels like a statically typed language but it has controllable dynamic typing via abstract type annotations. But multiple dispatch needs input type subsets somewhere, and argument annotations serve that purpose already. Earlier I said it’s not like either `typeassert` or `convert` kinds of type declarations, but it’s a bit more like the former: `foo(1.5::Int)` fails but `foo(1.5::Real)` runs, which is a really bad kind of method dispatch.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 14, 2023, 11:45pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/28 "2023-06-14T23:45:34Z")

</div>

I have edit my answer. I have, in fact, misunderstood what the manual meant. The manual does not make mention to `convert(AbstractFloat, x)`, and it is not clear what behavior should it have, if any. What the manual referred to was any `convert(T, x)` in which `T <: AbstractFloat` (and probably only cases in which `T` is a concrete type). Also, I said `x` where `x` is not obligatorily of type `Int`, but I did not really find a case in which the result type depended on the value (not the type) of the input.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 14, 2023, 11:48pm UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/29 "2023-06-14T23:48:12Z")

</div>

> [@Benny](#):
>
> I could very well need a `foo(x::Int)` method where `x` could be reassigned a floating point value, and I cannot refactor as a `foo(x::Real)`

Hmm, you’d do a `xf = Float64(x)` and use it hence-after, no?  
I don’t see, but ofc may be my problem, where what I’m saying would interfere with multiple dispatch. Annotated and non-annotated input variables would work as they do, just that, once a `police` through the door, always a `police` inside.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 15, 2023, 12:01am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/30 "2023-06-15T00:01:44Z")

</div>

> [@joa-quim](#):
>
> Hmm, you’d do a `xf = Float64(x)` and use it hence-after, no?

No. In a truly dynamically typed language, variables have to be able to accommodate unpredictable types from function calls. I said “could be”, not “will be” for that reason. Maybe an example will help you see it better. In your design proposal, a fully flexible variable would be annotated `::Any`

```julia
#=
I won't bother implementing this, but just know this
can return any type randomly
=#
function updatex end

function foo(x::Any)
  for i in 1:3
    x = updatex(x)
    println(x)
  end
end

foo(1)

```

Seems good so far, until I want the _input_ type to change what is printed. In current Julia, I can do this with argument annotations:

```julia
function foo(x::Integer)
  for i in 1:3
    x = updatex(x)
    println("Started as an Integer, now we're", x)
  end
end

function foo(x::AbstractFloat)
  for i in 1:3
    x = updatex(x)
    println("Floated down to a ", x)
  end
end

foo(1)
foo(1.5)

```

But that won’t compile in your design proposal, `updatex(x)` would be inferred as a `::Any`. But like you said, I don’t need to reassign `x` at all, I could just make another variable `x2`… but what type do I annotate it with? I often don’t know in advance what exact types a function call may return, even if I’m sure it’s type-stable. So I won’t annotate it at all, leave it as an implicit `x2::Any = x`.

But you see, we’re really back where we started: we selected a method using the input type, and we work with unpredictable types starting from there. The difference is we can’t reassign the argument variable and have to make an extra local variable.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 15, 2023, 12:15am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/31 "2023-06-15T00:15:11Z")

</div>

> [@Benny](#):
>
> ```julia
> function foo(x::Integer)
> for i in 1:3
> x = updatex(x)
> 
> ```

In my _design proposal_ (well, it isn’t really a proposal because Julia is not going to change) `x = updatex(x)` would error every time `update(x)` did not return an Integer because `x` had to retain its input type.

But

```julia
function foo(x::AbstractfFloat)
  for i in 1:3
    x = updatex(x)

```

should allow `updatex(x)` returning Integers that would be promoted to float.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 15, 2023, 12:17am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/32 "2023-06-15T00:17:04Z")

</div>

I think what Joaquim says that the language _could_ behave differently, more akin to a type-annotated language. I think he is correct, it _could_. It just doesn’t, and this does not seem something fundamental for the majority of Julia programmers, because we seek type-stability anyways by following some patterns and using some linter/code analysis tools.

But in many scenarios it is not unreasonable to expect the languages to behave like that, and people like statically typed languages for this reason. What I wander is is there some possible macro that, given some syntax (new or existing), give the same level of type certainty a statically declared language provides. For example, if one writes something like:

```julia
function foo(x)
    local x::Int
    local y::Int
    x = y + 1
    z = 2y
    return z
end

```

From what I see, if `x` and `y` are assigned to values not convertible to Ints, this will error. Good. If there was an analysis that warned the user that he/she “forgot” to declare the type of `z`, then one would be almost there (or totally there?) in terms of statically typed analysis. It wouldn’t be bad to have some tool providing that kind of analysis and guarantees.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 15, 2023, 12:23am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/33 "2023-06-15T00:23:15Z")

</div>

Thanks, I think it’s _almost_ that. The difference is what I’m saying is that the above example should apply when input `x` is annotated. _i.e._ `function foo(x::Int)`

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 15, 2023, 12:23am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/34 "2023-06-15T00:23:41Z")

</div>

> [@joa-quim](#):
>
> `updatex(x)` would error every time `update(x)` did not return an Integer because `x` had to retain its input type.

Which is awful for a dynamically typed language, and also not what a statically typed language would do. A statically typed language restricts to concrete types so it would be more akin to `x::typeof(x) = x` I said earlier, not `x::Integer = x`. The latter isn’t necessarily type-stable, either, there are many `Integer` types.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 15, 2023, 12:32am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/35 "2023-06-15T00:32:45Z")

</div>

Yes, it could be for the annotated input and output `foo(x::Int)::Int`, for example. But that is very limited in terms of type stability, because inside the function one would still be able to define other variables that change type at will. Thus, I was going a little bit further and requiring all variables to have their types explicitly declared. If that was combined with generic inputs, like:

```julia
function foo(x::T)::T where {T<:Real}
    local x::T, y::T, z::T
    y = x + one(T)
    z = x + y
    return z
end

```

and something/some tool can throw a warning if _any_ of the variables inside `foo` is not declared or may assume a wrong type, that would be nice.

But why we do not have that already? Because, I think, that is not much different from having simply

```julia
function foo(x::T) where {T<:Real}
    y = x + one(T)
    z = x + y
    return z
end

```

and use JET, Cthulhu or @code\_warntype to check for type instabilities for a specific set of inputs, without the variable declaration boilerplate.

---

<div class="post-metadata">

**Author:** ![de-souza](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/de-souza/32/43417_2.png) [@de-souza](https://discourse.julialang.org/u/de-souza)\
**Post date:** [June 15, 2023, 9:15am UTC](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322/36 "2023-06-15T09:15:02Z")

</div>

Tangentially relevant:

> [@Is it appropriate to say a variable is a label or box?](https://discourse.julialang.org/t/is-it-appropriate-to-say-a-variable-is-a-label-or-box/46068):
>
> I’m new to Julia, but not to programming, so to help me learn, I’m writing some notes and training material. While reading Python Crash Course, the author describes a variable as: Variables are often described as boxes you can store values in. This idea can be helpful the first few times you use a variable, but it isn’t an accurate way to describe how variables are interpreted in Python. It’s much better to think of variables as labels you can assign to values. You can also say a variable ref…

[Previous page](https://discourse.julialang.org/t/how-to-re-define-a-variable-completely/100322.md?page=1)
