Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't redefine (or undefine) function - better REPL text and documentation needed? #8586

Closed
PallHaraldsson opened this issue Oct 5, 2014 · 7 comments
Labels
docs This change adds or pertains to documentation

Comments

@PallHaraldsson
Copy link
Contributor

[If I do the same with a (new) g(x) function then everything is as expected or open a new session and do this.]

julia> f(x) = div(x, 100)
f (generic function with 2 methods)

julia> f(100)
1

julia> f(x) = div(x, 10)
f (generic function with 2 methods)

julia> f(100)
1

I was previously testing best way to do stuff with f(x) = x / 100
and then could redefine with f(x) = iround(x / 100)

and then, that seems to be the problem:
f(x::Int64) = div(x, 100)::Int64

For a beginner this would be a gotcha. I understand the precedence now, but not sure how I undefine f(x::Int64) now. Could/should the REPL, at least, say something else if not a warning (or override)? I know "2 methods" is a hint, but for me at first it looked like a bug.. Should this at least be mentioned clearly in the documentation?

julia> versioninfo()
Julia Version 0.3.1
Commit c03f413 (2014-09-21 21:30 UTC)
Platform Info:
System: Linux (x86_64-linux-gnu)
CPU: Intel(R) Core(TM)2 Duo CPU T8100 @ 2.10GHz
WORD_SIZE: 64
BLAS: libopenblas (NO_LAPACK NO_LAPACKE DYNAMIC_ARCH NO_AFFINITY)
LAPACK: liblapack.so.3
LIBM: libopenlibm
LLVM: libLLVM-3.3

Palli.

@simonster
Copy link
Member

In Julia, functions can have multiple methods, each of which accepts different types. The most specific method is called for any given set of types. (You can see the methods sorted by order of specificity by calling methods(f).) Given that defining multiple methods of the same function is extremely common in idiomatic Julia code (e.g. there are 148 methods of +), I don't think we should warn for it. I think this is pretty well documented in the Methods section of the manual.

@PallHaraldsson
Copy link
Contributor Author

Thanks, I know all this, still had my gotcha.. I could close this issue, just not sure something better would be done. However, I still can't "redefine" "my function" from the REPL. I'm not using a file, just hacking around in the REPL. Haven't found something like:

unset(f)

to start over.

Or:

unset(f(Int64))

I know I could exit and start julia again, but might (do) have other functions. [And can I get everything I have in my current "session" saved to a file? Or any way to get overview of what I've done, not just using the edit history..]

What might have helped - instead of:

julia> f(x) = x / 100
f (generic function with 1 method)

julia> f(x::Int64) = div(x, 100)
f (generic function with 2 methods)

julia> f(x) = div(x, 100)
f (generic function with 2 methods)

to get:

julia> f(x) = x / 100
f (generic function)

julia> f(x::Int64) = div(x, 100)
f (function with 2 methods) - 1 other less specific function. Do methods(f) to see all. And unset(f) to..

julia> f(x) = div(x, 100)
f (generic function) - 1 other more specific function. Do methods(f) to see all. And unset(f) to..

Doesn't have to say "warning". Just an idea.

Or maybe - here:

julia> methods(f)

2 methods for generic function "f":

f(x::Int64) at none:1 - Do XXX to unset.
f(x) at none:1

Regarding the documentation, I know it says somewhere you shouldn't use a type unless you really know what you are doing - you could say I really don't :) I was just messing around as the REPL is excellent for and people will do.. With:

f(x::Int64) = div(x, 100)::Int64

In my mind I was casting to Int64 (the latter) and didn't think of the former Int64 as a type declaration as much as a cast..

Maybe the text as I proposed would also have been overlooked.. and people will have gotchas anyway. I did however check http://julia.readthedocs.org/en/latest/manual/functions/#man-functions after the fact and many people will look under functions not methods.

@PallHaraldsson PallHaraldsson changed the title Can't redefine function - expected behaviour? Can't redefine (or undefine) function - better REPL text needed? Oct 6, 2014
@PallHaraldsson PallHaraldsson changed the title Can't redefine (or undefine) function - better REPL text needed? Can't redefine (or undefine) function - better REPL text and documentation needed? Oct 6, 2014
@pao
Copy link
Member

pao commented Oct 6, 2014

Very similar to #265, though I'm not sure it covers it completely. workspace() was recently added to stash the current context into the LastMain module and give you a fresh one, but this appears to be asking for something more targeted which would remove a specific method from the method table?

@JeffBezanson
Copy link
Member

More related to #2385. However the behavior from defining f(x::Int) then f(x) is absolutely fundamental. I don't think we can do anything about it. Most of us are not going to accept printing a long explanatory message every time a generic function is shown. But I think it would be fair to add a few sentences to the "functions" chapter hinting about this.

@PallHaraldsson
Copy link
Contributor Author

Just to be clear, I'm not asking for any major change to the visible behaviour (of precedence) or how calls get (re)optimized, so #265 seems do be different (but yes, workspace() "unset" f(x) and f(x:Int) and all functions I guess..). #2385 seems to be what I was after and I'm not sure why it's "probably Jeff's most hated feature request".. I however, just feel privileged that he commented on my first "bug" :) Even if he disagrees with my proposal..

[I guess I should use files and a "proper" IDE to edit my program.. the REPL has just been (very) good-enough for now..]

Now that I understand this well, do I close the bug or keep it open as maybe something could be done?

"accept printing a long explanatory message every time a generic function is shown", I'm not sure when that is, I only know about when you define or type in the function name. This is only a text for the REPL, right? Adding the constant text "methods() to see" or "methods(f)" would have helped (and if I can actually see the method that I haven't found out how).

If unsetting a function is not possible (at the moment) I tried to see if a manual workaround would work (that could then be implemented as "unset"):

julia> f(x::Int64) = f(x)
f (generic function with 2 methods)

julia> f(1000)
ERROR: stack overflow
in f at none:1

Seeing immediately where I went wrong.. :) I guess there is no way to call the more "general" function?

[Of topic: Which reminds me, I'm toying with (immediate) types, and I couldn't find a way to call the constructor of "super".]

@JeffBezanson
Copy link
Member

You can call a more general definition with invoke.

Right now there are no super types that have constructors; only abstract types can have subtypes, and abstract types don't have constructors.

@JeffBezanson JeffBezanson added the docs This change adds or pertains to documentation label Oct 14, 2014
@KristofferC
Copy link
Member

Perhaps this can be continued to be discussed in #20048? Please reopen if the linked issue is not similar enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This change adds or pertains to documentation
Projects
None yet
Development

No branches or pull requests

5 participants