Global variables const by default?

Relatively poor performance resulting from the use of non-const global variables comes up quite often in Julia context. Wouldn’t it be better if variables were const by default? Or at least global variables. If a non-const global is really needed, one could write

julia> mutable x=3.14

julia> x="abc"


julia> y=3.14

julia> y="abc"
ERROR: invalid redefinition of constant y

(This is of course not true output from present Julia 1.3.1)

Instead of mutable a different word could be used for variables, like typemutable which., however, seems a too long word.

The proposal would break existing code (perhaps a lot?). It is therefore aimed at a future major version upgrade of Julia.

While it is a good goal to lessen performance problems, there are a few problems I can think of off the top of my head:

This makes writing scripts much more of a hassle. Right now you can write quick scripts (slow, in global scope) and high performance code (in functions etc.). With this proposal you make half of that more annoying, and I assume people will be up in arms

If you think I am exaggerating, maybe you have missed what happened the last time Julia became a little less global, when

julia> x = 1

julia> for i in 1:2
         x = i

julia> x
1  <----

stopped working the way a lot of people expect it.

Besides, you can’t change a const without restarting Julia. If you, by accident, grabbed a good variable name like x without making it mutable, you are now stuck with that for the rest of your session. This happens to me pretty much every time I am overly eager to make my variables constant and change my mind later.

I think the benefits gained from this (people don’t have to be told to watch their globals the first time they run into this) doesn’t outweigh the hassle for everyone to mark their variables as mutable, when they want to hack together a quick script.


As far as I understand it the present const in Julia means that the type is constant, not the binding (or the value):

julia> const z=3.14

julia> z=1.0
WARNING: redefining constant z

The warning should in my opinion be removed. Present Julia has, unlike many other languages, no way to enforce that a variable does not change. This, I think, is fine. After all, linguistically the concept of a constant variable is contradictory.

I guess with this a large fraction of the “quick scripts” would still work as commonly expected, even if variables were “typeconstant” by default.

const does mean that the binding is constant:

julia> const foo = 3

julia> f() = foo
f (generic function with 1 method)

julia> f()

julia> foo = 4
WARNING: redefining constant foo

julia> f()

If you have hashed out everything then yes, this is true. However, I often have snippets like (copied from something I’m working on currently):

data = xf["Run1"]["A4:AU19"]  # from an .xlsx file
data = data[2:end, 2:end] .|> float |> transpose

where I gradually change the type as I find out in what form I want to have the data. Of course this is getting cleaned up when I’m done but for exploration and messing around I find this quite convenient.

1 Like

Perhaps my concept of “binding” is wrong, but in your code the binding of foo changed, and not the binding of f(). Continuing I got:

julia> f()=foo   <--- new binding of function f
f (generic function with 1 method)

julia> f()

and then

julia> f=4
ERROR: invalid redefinition of constant f

So functions behave already like now proposed for variables: They can be rebound (without warning), but once a name is a function, it is always a function (until the end of the session).

In most (library) code, globals are not needed at all. The best approach is not to make them constant, but to avoid global variables altogether.

At the same time, (nonconstant) globals are enormously useful for interactive work, so let’s keep them simple.


The fact that a warning is printed means that changing const bindings is not properly supported (otherwise, why show a warning?). It doesn’t error because it can save some annoyance in the REPL but you don’t really know what has cached that constant so it shouldn’t be used anywhere except when toying around in the REPL.


To be clear this is a breaking change so can’t be considered, except in the context of “What should we be thinking about for Julia 2.0, some time years in the future.”

With that said, I am personally Pro that kinda discussion.
So do continue


Yes, this would break both existing code and habits.

Probably it is difficult to say how much code this would break and how disturbing it would be for the work flow without actually trying it. However, unlike the example given by @Karajan , there would be no subtle bugs (“the value of variables magically changes”), but only firm errors. Automaticed code fixes throwing in mutables seem possible.

I think that the proposal, to have variables type constant be default, but mutable binding, would overall harmonize the Julia language, i.e. variables then behave more similarly as already structs and functions.

Another conclusion from the discussion so far might be that the meaning of const in Julia seems not obvious in the present version, constant type, constant binding etc? This could perhaps be addressed earlier than in some time years.

As explained in its docstring (?const),

In some cases changing the value of a const variable gives a warning instead of an error. However, this can produce unpredictable behavior or corrupt the state of your program, and so should be avoided. This feature is intended only for convenience during interactive use.

See the rest, it should be pretty clear. TL;DR: you are promising constant values, but may be allowed to change them with a warning.

Ok, thanks, this is clear.

This sounds like a good idea, but I actually think it is pretty problematic. Given Julia’s model, one wants to keep the REPL session open as long as possible, to avoid recompilation. If globals were const by default, one would tend to pollute the sessions top namespace with many const bindings that cannot be removed without restarting. Imagine saying a = 3 and getting an error because a was already a String, say, and having to traverse the alphabet looking for an unused name. Not nice.

EDIT: This already happens with names of functions and structs, of course, but these tend to be more verbose


One would have to remember to type mutable a=3 (mut<tab> a=3) each first time in a session when a global for toying around in the REPL is declared. Personally I think, that I could get used to this.

With the proposal the performance of code translated from other languages (like Matlab) into Julia would not suffer when global variables are involved and not declared const. Right now such translated code seems frequently to be a source of disappointment.

Making globals constant is not the right solution to the performance problem caused by non-constant globals.

Overusing globals (which, in most cases, using any) is simply bad style in Julia, and most modern languages. It makes it very difficult to reason about code, precludes various compiler optimizations (even for constant type containers).

Instead of encouraging it, one should avoid direct translation of code that uses globals for nontrivial computations (ie anything with flow control) in non-exploratory code.


What about raising a PerformanceWarning if non-constant globals are used inside a function?
This would give the programmer a clear indication that this is not good (not only for performance reasons). On the other hand, it would not prevent usage of globals while hacking in the REPL.

This is what Traceur.jl does.


In most posts where the OP is seeing worse than expected performance, it is clear that the OP has not read any of the numerous other threads on the topic on this forum, neither the performance tips in the manual. Changing the language to accommodate this kind of user is probably not the right way to go about it, actually, a discourse bot could probably identify and prompt such users already while the post is being written, to read the performance tips before posting.


Thanks for pointing this out, looks very useful, I’ll take a closer look.

However, I think for beginners (who probably neither know Traceur nor @code_warntype yet) such a PerformaceWarning would be useful.
Especially if people do benchmarking of various languages (without being deep into all of them), this could give misleading results.

The warning could also be very annoying to those who are aware of the problem but choose to program in a certain way for other reasons. Also to be fair, both these tools are listed in the manual so beginners who take the time to read the manual will know about them. Beginners who do not take the time to read the manual perhaps can’t expect to achieve maximum performance?