Reputation: 45
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=9
and 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
.
Upvotes: 3
Views: 441
Reputation: 31342
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:
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.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.
Upvotes: 3
Reputation: 69839
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 calledLib
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 byLib
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 inLib
.
and
Once a variable is made visible via
using
orimport
, 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.
Upvotes: 7