PKumar
PKumar

Reputation: 11128

How to reset any function in Julia to its original state?

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

Answers (1)

AFAIU, the rationale for this behavior is as follows:

  1. 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).

  2. 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

Related Questions