2
votes

I'm currently programming on Julia via command line session.

I know that the predefined functions in Julia (e.g. sqrt) can take on a variable value but in a particular session I tried to use the function as sqrt(25) and it gave me 5.0 but in the same session when I wrote sqrt=9, then it says

"Error: cannot assign variable Base.sqrt from module Main"

and if I have to make this happen I have to open a new session all over again and assign a variable value to sqrt sqrt=9and when I do so then again it says

ERROR:MethodError: objects of type Int64 are not callable

when I try to use sqrt as a function.

The same thing happens with pi.

2
I don't really understand the problem. What you are describing seems to be the expected behavior. If you want to avoid it either use Base.sqrt rather than using sqrt or refrain yourself from assigning predefined functions.PilouPili
Could you rephrase your question so it becomes more clear where you require help or what remains unclear?user172056
@Harsh Shukla: indeed it would be good to clarify the question. My answer is based on what I guess is your question, as I get questions related to rebinding of variables imported from other modules on most courses on Julia I teach.Bogumił Kamiński

2 Answers

6
votes

The topic you are asking about is a bit tricky. Although I agree with the general recommendation of PilouPili it is sometimes not that obvious.

Your question can be decomposed into two issues:

ERROR:MethodError: objects of type Int64 are not callable

This one is pretty clear, I guess, and should be expected if you have some experience in other programming languages. The situation is that name sqrt in the current scope is bound to value 9 and objects of type Int64 are not callable.

The other error

"Error: cannot assign variable Base.sqrt from module Main"

is more complex and may be non obvious. You are free to use name sqrt for your own variables in your current scope until you call or reference the sqrt function. Only after such operations the binding to sqrt is resolved in the current scope (only recently some corner case bugs related to when bindings are resolved were fixed https://github.com/JuliaLang/julia/issues/30234). From this moment you are not allowed to change the value of sqrt because Julia disallows assigning values to variables imported from other modules.

The relevant passages from the Julia manual are (https://docs.julialang.org/en/latest/manual/modules/):

The statement using Lib means that a module called Lib will be available for resolving names as needed. When a global variable is encountered that has no definition in the current module, the system will search for it among variables exported by Lib and import it if it is found there. This means that all uses of that global within the current module will resolve to the definition of that variable in Lib.

and

Once a variable is made visible via using or import, a module may not create its own variable with the same name. Imported variables are read-only; assigning to a global variable always affects a variable owned by the current module, or else raises an error.

To better understand what these rules mean I think it is best to illustrate them with an example:

julia> module A
       export x, y
       x = 10
       y = 100
       end
Main.A

julia> using .A

julia> x = 1000
1000

julia> y
100

julia> y = 1000
ERROR: cannot assign variable A.y from module Main

on the other hand by calling import explicitly instead of using you resolve the binding immediately:

julia> module A
       export x, y
       x = 10
       y = 100
       end
Main.A

julia> import .A: x, y

julia> x = 1000
ERROR: cannot assign variable A.x from module Main

And you can see that it is not something specific to Base or functions but any module and any variable. And this is actually the case when you might encounter this problem in practice, as it is rather obvious that sqrt is a predefined function, but something like SOME_CONSTANT might or might not be defined and exported by the modules you call using on and the behavior of Julia code will differ in cases when you first assign to SOME_CONSTANT in global scope and when you first read SOME_CONSTANT.

Finally, there is a special case when you want to add methods to functions defined in the other module - which is allowed or not depending on how you introduce the name in the current scope, you can read about the details here what are the rules in this case.

2
votes

Bogumił's answer is good and accurate, but I think it can be described a bit more succinctly.

Julia — like most programming languages — allows you to define your own variables with the same name as things that are built-in (or more generally, provided by using a package). This is a great thing, because otherwise you'd have to tip-toe around the many hundreds of names that Julia and its packages provide.

There are two catches, though:

  • Once you've used a built-in name or a name from any package, you can no longer define your own variables with the same name (in the same scope). That's the Error: cannot assign variable Base.sqrt from module Main: you've already used sqrt(4) and now are trying to define sqrt=2. The workaround? Just use a different name for your variable.
  • You can define your own variable with the same name as a built-in name or a name from any package if you've not used it yet, but then it takes on the definition you've given it. That's what's happening with ERROR: MethodError: objects of type Int64 are not callable: you've defined something like sqrt=2 and then tried to use sqrt(4). The workaround? You can still reference the other definition by qualifying it with its module name. In this case sqrt is provided by Base, so you can still call Base.sqrt. You can even re-assign sqrt = Base.sqrt to restore its original definition.

In this manner, the names provided by Base and other packages you're using are a bit like Schrödinger's cat: they're in this kinda-there-but-not-really state until you do something with them. If you look at them first, then they exist, but if you define your own variable first, then they don't.