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.