Underscores.jl icon indicating copy to clipboard operation
Underscores.jl copied to clipboard

Audit _ expansion rules to only expand into "things which look like function calls"

Open c42f opened this issue 5 years ago • 4 comments

We've had a couple of specific cases where _ expansion is confusing - opened in #6 and #8 and solved by #10.

But because #10 is breaking, I'd like to make sure we have a single consistent-as-possible syntax rule before the next release. Something like:

_ expands to a closure which is passed to the outermost "thing which looks like a function call"

See #6 and #8 for extensive discussion.

c42f avatar Jul 08 '20 01:07 c42f

One question is what to do with macros, it seems that this should work, since it doesn't look like a function call:

@_ data |> @view map(_.re, __)[1:3]

but as you mentioned in #8, sometimes you will need brackets:

a |> @m b |> c   # parsed as  a |> @m(b |> c)

Would it be crazy for @_ to re-organise such things to a |> (@m b) |> c?

mcabbott avatar Jul 08 '20 09:07 mcabbott

Would it be crazy for @_ to re-organise such things to a |> (@m b) |> c?

I think it's a bit dangerous to second guess the language parsing rules, I think it will lead to irregularities and surprises in the longer term.

For example, the user could write this as a |> @m(b |> c) and they'll be quite surprised when we rearrange the whole thing :-)

c42f avatar Jul 27 '20 00:07 c42f

An interesting case from https://github.com/c42f/Underscores.jl/issues/18#issuecomment-683570078 which I agree should work.

julia> any(>(3), 1:4) ? "yes" : "no"
"yes"

julia> @_ any(_>3, 1:4) ? "yes" : "no"
ERROR: TypeError: non-boolean (var"#13#14") used in boolean context

c42f avatar Sep 03 '20 05:09 c42f

Note that such examples won't work very well in pipelines -- I'm unsurprised by (0 |> string) here but was a little surprised by (data |> cond):

julia> :(data |> if any(_,__) 1 else 0 end |> string) |> Meta.show_sexpr
(:call, :|>, (:call, :|>, :data, (:if, (:call, :any, :_, :__), (:block,
        :(#= REPL[14]:1 =#),
        1
      ), (:block,
        :(#= REPL[14]:1 =#),
        0
      ))), :string)

julia> :(data |> any(_,__) ? 1 : 0 |> string) |> Meta.show_sexpr
(:if, (:call, :|>, :data, (:call, :any, :_, :__)), 1, (:call, :|>, 0, :string))

mcabbott avatar Sep 03 '20 14:09 mcabbott