-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
disallow methods of local functions in different blocks #15602
Comments
This isn't allowed any more; I'll have to come up with a better error message. Now you need to do
|
Is there a reason why this is no longer allowed? |
Yes; this restriction makes it possible to hoist construction of
Here,
|
Yeah, I found those workarounds. Thanks for explaining it. Now that I know there's a reason it's easier to remember. I think that this should say something like However, to make it a little more user friendly, my example function g(a)
if a
f() = 2
else
f() = 3
end
return f
end
f = g(true)
f() # Returns 3 shouldn't error with |
Perhaps this should be documented in NEWS.md as @josefsachsconning pointed out. |
Documentation pretty crucial, since this is a breaking change. |
Would it not be better for this to generate an error instead of a warning? |
Would it be possible to automatically do the renaming that the workaround implements? |
It's iffy; the general case is very complicated. For example
describes 2^n different functions. |
Thinking about it some more, I could almost imagine treating definitions in different basic blocks like separate functions. In other words this:
would return a function with two methods (returning 2 or 4) for |
If you're treating definitions in different blocks like separate functions, wouldn't that break: function g(a,b)
if a
f() = 2
end
if b
f(x) = 4
end
f
end as in, what would it return for |
That case is already broken. For now at least, our choices are to disallow it (since it doesn't do anything reasonable) or give it another meaning. Have you used that pattern? In my informal survey of packages during this change I don't think I found any uses of it, though there were several uses of the pattern in the OP. For reference, my proposal would return a function with the one method
|
That seems extremely confusing. How about detecting if we're in a case that can be refactored like that while giving the expected behavior and error only if that's not the case? I.e. support the if/else case (which does occur) but raise an error in the if/if case (which seems not to). |
@JeffBezanson I did have something like that before, i.e. adding dispatches conditionally. But I think one reason why you won't find any uses of it is because everything related to this issue has such non-intuitive behavior that any package is probably avoiding anything like this (for example, I changed some codes away from conditional definitions like this to all using anonymous function when I did the change from v0.4 to v0.5 a few months ago). I think that checking which packages are using the broken design pattern, seeing none are using it, and then declaring that it must not be wanted is kind of a self-fulfilling prophecy. That said, I don't think it's a necessary design pattern. I've avoided it now for awhile and haven't needed it since. I like what @StefanKarpinski is suggesting: you know that the design pattern is going to have issues, so instead of letting odd behavior happen, throw an error. Otherwise it's one hell of a bug to debug. I'd rather be told to avoid it rather than try to make it work. |
@ChrisRackauckas I did that survey while working on this change, before it was pushed to master, so it was 0.4 code only. But yes, my default choice here would be to give an error (#15602 (comment)), I just thought I'd throw out another alternative. Allowing the
I figured it might be easier to reason about what is in separate blocks, vs. which blocks the compiler can tell are mutually exclusive. |
Got it. Thanks for the clarification. |
Anonymous-ness does not make a difference here; the construct
That approach can be safely used to add multiple methods to an anonymous function. It's really just that there's no syntax for an anonymous function with multiple methods. One could write a macro for that though, e.g.
With the DiffEq example, say you are tempted to write
The correct way to write it is:
|
Setting aside the question of how to support this better, can the obviously broken case be made to error? The example above by @bkamins is particularly bad; no warning at all is delivered, the |
I agree with @antoine-levitt , the fact that code inside the |
Agree. It would be great if someone took on figuring out how to make this warn in the problematic cases, or better still an error since it's unlikely to be doing the right thing in any code doing this. |
Recently ran into this as well... how about making the default option to warn such overwrites, i.e. change this to Line 57 in 52c55d7
then add a way to programmatically suppress the warning/error message when the overwrite is intentional, such as Revise.jl? e.g. a macro like Lines 1497 to 1510 in 52c55d7
One possible way to implement is by adding a function to flip the warning setting, JL_DLLEXPORT void jl_options_flip_warn_overwrite(void)
{
jl_options.warn_overwrite ^= 1;
} then in julia, the warning can be turned on/off via |
Always show the warning for anonymous functions, but update the verbiage to give additional information. This warning can still be avoided by explicitly calling delete_method first. fixes JuliaLang#32635 fixes JuliaLang#35140 refs JuliaLang#15602
I ran into this issue today. I would love to see this error out at lowering time. |
What is the issue preventing a more comprehensive error here? Do we just not know the precise conditions under which we should allow / disallow this kind of construct? What about disallowing method definitions for an inner function unless they are all in the same basic block? |
As a new user, I've stumbled accross one case here that I find very dangerous, because Julia produced definite undesired behaviour with no warning (i.e. evaluating |
Could someone please comment on the plans related to this issue? Thank you! (I am asking because the problem is often raised by new Julia users) |
In Julia 0.5.0-dev+3171 the following code creates a bogus duplicate function definition warning.
The text was updated successfully, but these errors were encountered: