-
Notifications
You must be signed in to change notification settings - Fork 3
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
Behavior of _
is confusing with infix operators
#6
Comments
Just happened to see this; I can answer your question (though I'm not the author of this package). The error indicates that The problem is that v |> a -> ((b -> sum(b.x, a)) / length(a)) Presumably you wanted this. v |> a -> (sum(b -> b.x, a)) / length(a)) |
Yes, you are right. v = [(x = rand(), y = rand()) for _ in 1:10]
@_ v |> sum(_.x, __) / 10 produce the same error. So the question is, is it possible to do what I want with the current syntax or modify it somehow to solve this issue. Both answers are perfectly fine. |
I can see why this led to confusion: the @_ v |> division(sum(_.x, __), length(__)) Unfortunately macros cannot see whether something "looks like a function call". I guess we could prohibit use of Regardless of all that, the following is vastly more readable to my eyes: @_(sum(_.x, v)) / length(v) |
So... I think we can take this as either a documentation issue, or a code cleanup where we deprecate the use of It's fiddly though: are there some operators which are higher order functions? |
_
is confusing with infix operators
I feel like maybe a pure documentation-based approach is the best for now. In the future macros may well gain the ability to "see the parentheses" with a more detailed introspection of the source code in some compiler work I'm doing. So a much longer-term plan might be to disallow use of |
To clarify, it was a part of a longer chain (sorry, I am spoiled by R). Expanding on MWE v = [(x = rand(), y = rand()) for _ in 1:10]
@_ v |> filter(_.x > 0.5, __) |> sum(_.y, __)/length(__) Of course it's not a problem, to use @_ v1 = v |> filter(_.x > 0.5, __)
@_ (sum(_.x, v1)) / length(v1) but it felt rather natural(?) to use underscore this way. Is it possible to do a rule like "any __ should be changed to a new variable, no matter where they appear"? Something like |
I think the Double underscore: julia> @macroexpand @_ df |> a(__)/b(__)
:(df |> ((__1,)->begin
a(__1) / b(__1)
end)) Single underscore: julia> @macroexpand @_ df |> sum(_, xs)/len
:(df |> ((_1,)->begin
sum(_1, xs)
end) / len) see what's happened? It's that So the problem is the "outermost-but-one" rule for expanding the Of course, as programmers we can guess this is complete nonsense! But from a syntax tree point of view it's the consistent rule the whole expansion is based around. As I said above, it could be hacked around by not treating operator function names as valid calls which can accept an anonymous function. But this would be heuristic, because |
Thank you for the explanation! |
So... deciding what to do about this is really tricky and I didn't anticipate encountering this problem with an explicit Perhaps I should have — almost exactly the same problem has been discussed at length in JuliaLang/julia#24990 (though for tight-binding rather than loose binding). |
While infix operators are ordinary function calls, Julia does seem to regard the infix form as the standard one: julia> :( +(2, 3, *(4, 5)) )
:(2 + 3 + 4 * 5) Perhaps that supports the idea of always treating them this way, and thus letting the macro work inwards until it finds an honest prefix function call. Are there any infix operators which would accept a function? Besides |
Yes, agreed this is the right thing (as mentioned in #8 (comment)). BTW we have Note that |
I do not know, whether it would be useful, but I've got another similar (I suppose) issue.
It looks similar to #8 and I hope #11 solve this case as well. |
That case isn't currently handled by #10, although I think it would make sense to add. |
Yes I think that's the same as #8 basically: we should recurse into both the |
Not sure whether it's a bug or wrong usage of
Underscores.jl
, but following example failsThe text was updated successfully, but these errors were encountered: