Defining a function inside if...else..end NOT as expected?

It can sometimes be useful to add methods to anonymous functions. The example below shows how it’s done and also shows that multiple dispatch works fine for anonymous functions

julia> f = (a::Int) -> println("Int")
#719 (generic function with 1 method)

julia> (::typeof(f))(a::Float64) = println("Float")

julia> f(1)
Int

julia> f(1.)
Float

julia> f
#719 (generic function with 2 methods)

julia> methods(f)
# 2 methods for generic function "#719":
[1] (::getfield(Main, Symbol("##719#720")))(a::Float64) in Main at none:1
[2] (::getfield(Main, Symbol("##719#720")))(a::Int64) in Main at none:1
5 Likes

Anonymous functions are just generic functions with “unpronounceable” names, so they work in exactly the same way.

1 Like

I tried to use anon functions for my example at first, but that did not work

julia> function foo()
           f = (x::Number) = x^2
           (::typeof(f))(x::Vector) = sum(x)
           f
       end 
ERROR: syntax: Global method definition around REPL[1]:3 needs to be placed at the top level, or use "eval".

That’s the wrong syntax for defining a function
It should be f = (x::Number) -> x^2

right, I made a typo trying to reproduce my example. statement still holds though.

This works, but I’m not sure if it’s the recommended way of doing things.

function foo()
    f = (x::Number) -> x^2
    @eval (::typeof($f))(x::Vector) = sum(x)
    f
end

julia> f = foo()
#817 (generic function with 2 methods)

julia> f([3])

3

julia> f(3)
9

Edit: This has changed since Julia v0.6 where @eval was not needed and the example you posted first works without error.

1 Like

I am sorry to bother everyone in the thread, but I happened to bump into this problem just now. I sort of understand the arguments given here and also the workarounds suggested. However, I don’t even dare to think about how many buggy codes are running out there with their author having no clue about this utterly contra-intuitive “feature”. I don’t know if there are other languages that trick you in a similar way, I certainly don’t know of any and Julia is not the only one that I have been using. At the very very least, a warning should be issued when a user defines the same function at several places within the same scope. Please! I admit this is the first time I bump into this issue, still I think such a warning really shouldn’t be that hard to implement.

This is my stripped-to-the-bone code that I got after a lengthy debugging.

function test(i)
    if true
        f(j) = 1
    else
        f(j) = i
    end
    f(0)
end
test(137)

My wild guess is that one out of a million Julia users would guess here correctly that the output is 137.

The issue to track is disallow methods of local functions in different blocks · Issue #15602 · JuliaLang/julia · GitHub.

4 Likes

Thank you for the link! Apparently it takes a number of years, but sustained push from the community will hopefully lead somewhere eventually.

Given that the issue on this was opened 4 years ago I’d guess it isn’t quite as simple as one might hope…

@colintbowers So you suggest that Julia devs have been working for 4 years on issuing a warning when you define a function for a second time? Because that is the context out of which you took the quote from me.

We agree that this is a far cry from solving the issue itself, right?

While the problem that you encounter no doubt seems like the most important problem to be solved, this particular problem has not made it to the top of the todo list of those who work on Julia’s parser and compiler. If you believe this is not hard to implement, a contribution would be most welcomed.

10 Likes

@StefanKarpinski You earned some likes here, my post probably won’t be that popular. :wink:

Are we still talking about that warning message that I am suggesting in my original post? Or everyone is overseeing the context and gets triggered by the words “shouldn’t be that hard to implement” and automatically assums that I cannot appreciate the complexity of the issue itself that got raised 4 years ago?

If any Julia developer is reading this: could you please give an honest and realistic estimation how much it would take to implement the following: zero change to the actual inner workings of Julia, but only detecting multiple function definitions made within the same function or where else this matters, and then issue a warning saying that “you will probably not get the results you expect, please refer to this page of the manual”? Because this is all I am suggesting, like in my original post. I am only asking for a warning sign, that “Dangerous road ahead!” not that they repair the road itself. And not even for myself. I already know about this problem very well. But for others who would otherwise suck with it as much as I did.

With all due respect, maybe one last thing: I find it a tiny bit intimidating and little constructive that innocent estimates on difficulty of solving some problems are met sometimes with the response that your contribution would be welcome. Yes, thank you for the invitation to contribute, but I have to say, it sounds a bit like, if you cannot or you’re not willing to contribute, please don’t give us estimations on how much work this would take. For one, I am happy to stand corrected if a dev tells me that unfortunately this is more complex than that, etc… For two, coding is really no sorcery either. Julia users themselves are coding a bit even if they are not pros. Eg. I have a guy who does my tax returns. I could do it too, but for me it would take ages just to read all the regulations and then complete my tax declaration properly, while it takes an hour for him to do the same. Yet, I can mostly tell with certainty what can be deducted, and what is not worth taking the trouble. So unless you are a Julia dev, and you actually know better how much it would take to implement that warning only, your guess is as good as mine. And yes, a contribution would be much welcome, but it won’t come from me. I take my own share of contributing to other stuff enjoyed by society and I do for free. What makes sense though is for everyone to do what they are skilled and versed to do. And be a bit friendlier if “outsiders” dare to comment on it. On the other hand, if this is actually meant to be a recruiting tactic, it’s not the best. At the very least, it is too easy to misunderstand it as “fix it or put up with it”. I am really sorry, I don’t mean to be hurtful either, please don’t get offended, but I honestly feel a bit of intimidation in some recent responses to my post not to speak of that my words are apparently taken out of context. I apologize for my ranting anyway, and unless I get some constructive response, I am leaving this conversation. No hard feelings on my side though, I hope you feel the same way.

1 Like

Stefan is one of the 4~6 people which started Julia, i.e., one of the creators. I would trust him in this issue.

1 Like

@Henrique_Becker, thanks for the info. I would then love to hear his opinion on “how much it would take to implement that warning only. @StefanKarpinski,…

Giving this estimate with a very short explanation (I would love it, but I will take your word for it anyway), could shortcut this discussion. I am looking forward to Stefan’s answer.

To estimate the time taken by some task, you have to discover how to do such task, and sometimes this is 90% of the effort of implementing something. If this issue was not considered a priority until now, it is possible a precise estimation of how much time it takes will not be a priority either.

2 Likes

@Henrique_Becker
I would even accept an answer like “Sorry, it’s even hard to tell. I don’t know how hard it would be to implement.” I would be surprised, but I would take it from him. Fine, I was mistaken. Still I would find it a nasty bug, one that is worth at least a closer look.

Anyway, if he is aware of nontrivial difficulties about the problem (just the warning!), it would be fair to say so before inviting my contribution. I am most likely a regular user here, and well, yes, I am. So Stefan would honestly think that I just say alright, and go and implement what he found hard?.. Possible, but likely?.. If I was one of the greatest experts in a particular field, I would at least give a fair warning (again the warning :sweat_smile:), that “Hey, I am one of the main devs here, and we are not aware of any easy implementation even for the warning. If you have one, that would be great to share.” That would sound totally different to me.

He kinda already gave a disclaimer but it was not for only the warning.

I think the main question is: the problem is non-trivial and is not a priority; also, Julia is driven by community contributions, the language would not have reached the current state without them. As efficient the creators are, there a lot of work to be done, and everything that can be outsourced to a willing open source contributor should be outsourced.

1 Like

@Henrique_Becker @StefanKarpinski

Still it blows my mind that it has no priority that this gives 42 without a warning.

function test()
    if true
        f() = 137
    else
        f() = 42
    end
    f()
end

Anyway, I get all of this, Henrique. I have read the part you quoted before my original post. Unlike others who answer me without reading mine. For the last time, I am focusing on a warning only. It hasn’t been written down anywhere yet if a warning is also non-trivial (this is what I would like to know eg. from Stefan), neither that this can’t have a priority either. And as a regular user, having no better means, why I couldn’t just register an up-vote here for only a warning at least?.. I am not expecting anyone to jump on a problem right away that is important to me. This particular problem is not even important to me any more. I don’t need that warning, others would need it. According to me, a regular user, the project would need it. I thought that feedback was welcome too. Sorry for my post being

I will probably stop giving my opinion on the project.

   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.6.0-DEV.1527 (2020-11-19)
 _/ |\__'_|_|_|\__'_|  |  Commit e402cf47dd (0 days old master)
|__/                   |

julia> function test()
           if true
               f() = 137
           else
               f() = 42
           end
           f()
       end
WARNING: Method definition f() in module Main at REPL[1]:3 overwritten at REPL[1]:5.
test (generic function with 1 method)

It does give a warning on nightly, meaning in the next minor release of Julia there will be a warning. (You could find this by clicking on the issue @kristoffer.carlsson linked and seeing that there’s a PR adding a warning that links to it.)

7 Likes