Reputation: 11128
I am learning Julia, Here is something I am unable to figure out.
Case1: I started Julia console and overridden the default sqrt
function with a number 10. So now the function doesn't work. To me coming from R its bit of surprise, In R usually even if we override a function it works because of the method dispatch. Clearly, Julia's way of doing it is different which is okay. But now I am unable to reset to its natural state. I have to restart Julia to make it(sqrt
) work again.
julia> sqrt = 10
10
julia> sqrt(5)
ERROR: MethodError: objects of type Int64 are not callable
Stacktrace:
[1] top-level scope at REPL[2]:1
julia> sqrt = Nothing
Nothing
julia> sqrt(5)
ERROR: MethodError: no method matching Nothing(::Int64)
Closest candidates are:
Nothing() at boot.jl:324
Stacktrace:
[1] top-level scope at REPL[4]:1
Case2: I started Julia console and used sqrt
function to calculate things and it worked. But now if I try to reset to a constant it's not working. (I am assuming its because its compiled already and hence can't be overridden).
julia> sqrt(7)
2.6457513110645907
julia> sqrt = 10
ERROR: cannot assign a value to variable Base.sqrt from module Main
Stacktrace:
[1] top-level scope at REPL[2]:1
My question is:
Is there any way to reset the function to original state without restarting Julia? Also is my assumption for case2 is correct?
I am not sure if its already answered somewhere. I tried to find it out, but couldn't. I am still giving a read on this thing. But asking for help if anyone knows this. Thanks in advance.
Upvotes: 1
Views: 564
Reputation: 20248
AFAIU, the rationale for this behavior is as follows:
when you run sqrt(5)
in a program, it means that you know about the sqrt
function. If, later on, you try to assign a new value to sqrt
, Julia forbids you to do so, on the grounds that sqrt
in your program actually refers to the Base.sqrt
function, which is a constant. (Note that the same is true of any function that got exported by a package you're using
; there is no specificity related to Base
here, except that you don't have to explicitly using Base
in order to be able to call the functions it defines).
if you don't use sqrt
first as a function, Julia can't assume that you know about Base.sqrt
. So if the first mention of sqrt
in your program is an assignment, it will happily create a new variable of that name. This makes Julia more future-proof: suppose that you write a program that declares and uses a variable named foo
. As of Julia 1.5.3, no Base.foo
function exists. But now imagine that Julia 1.6 introduces a Base.foo
function. We wouldn't want such a change to break your existing code, which should continue working with newer Julia versions. Therefore the safe choice in this case consists in letting you freely declare a variable foo
without worrying about the name collision with Base.foo
.
Now in the case where you accidentally create in an interactive session a global variable that collides with an existing function, a simple solution would be to simply reassign your variable to the function from Base
(or whichever module the original function came from):
julia> sqrt = 1
1
# Oops, looks like I made a mistake
julia> sqrt(2)
ERROR: MethodError: objects of type Int64 are not callable
Stacktrace:
[1] top-level scope at REPL[2]:1
# Let's try and fix it
julia> sqrt = Base.sqrt
sqrt (generic function with 20 methods)
julia> sqrt(2)
1.4142135623730951
Upvotes: 3