Puzzling behaviour when assigning to variables which are function names

Coming from R I am a bit puzzled by how namespaces are handled in Julia.

julia> cos(3)
-0.9899924966004454
julia> sin = 0
0
julia> cos = 0
ERROR: cannot assign a value to variable Base.cos from module Main
Stacktrace:
[1] top-level scope
  @ REPL[3]:1
julia> Base.sin(3)
0.1411200080598672
julia> Base.exp(3)
20.085536923187668
julia> exp = 0
0

I do understand what’s happening here, there is some lazy loading going on, so I can assign to sin, but not to cos because I’ve already used it.

However, I have not indicated explicitly anywhere that I want to assign to Base.cos, and indeed, that’s not what I do when I assign to sin. And not to exp, presumably because I used the Base. prefix.

Although this is not a big deal, it’s symptomatic of a broader problem. There are hundreds of functions in Base, and in other modules. Many of which one is not aware of. If, by ignorance, you use one of these names for your own variable, and then later modifies your code to use the function of the same name in Base (or an upgrade suddenly adds that name to Base), things break down.

Moreover, it also discourages the use of commonly used names in modules, because it can interfere with users’ code, as in https://github.com/JuliaLang/julia/issues/35538

I don’t have a solution to this, though I know that in R similar issues are solved by having different namespace lookup-tables for function calls and variables. I.e. you can assign a variable in your current namespace, but if you call it as a function, a search for a function in your attached namespaces is performed. (But then, in R, non-function objects are not callable as in Julia.)

2 Likes

Exactly.

Since you used it, it is now in your namespace as a function.

Sure, but you will get an error message so you can investigate and fix.

Users can selectively import only what they need, eg

using ThatModule: foo

or just use a qualified

ThatModule.foo

Yes, R is Lisp-2 and Julia is Lisp-1 (corrected, thanks @sgaure). It is a design choice, both alternatives have advantages and disadvantages; you can find extensive discussions about this.

4 Likes

Eg one of the classical papers is Gabriel (1988).

1 Like

It’s the opposite, I believe. R is Lisp-2 (CL), Julia is Lisp-1 (Scheme). My point is that for a general language with a large number of general packages with functions that users may not be aware of, it is a problem for package developers to try and avoid names which users might like to use for their own purposes. It doesn’t help a lot that avoidance of name-clashes depends on lazy loading, rather it can add to the confusion.

For types it’s less of a problem, because the tradition is to capitalize them, whereas user variables are not.

But, as you say, everything has pros and cons.

1 Like

The point of this is so that code that looks like

using Foo
bar = 2

will not break if Foo starts exporting a variable called bar.

7 Likes