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

infix .* parses differently than standalone .* #38176

Open
pdeffebach opened this issue Oct 26, 2020 · 1 comment
Open

infix .* parses differently than standalone .* #38176

pdeffebach opened this issue Oct 26, 2020 · 1 comment
Labels
docs This change adds or pertains to documentation

Comments

@pdeffebach
Copy link
Contributor

I really appreciate #37583, it will hopefully make metaprogramming easier.

However I don't think the full features of .* etc. work properly yet. Here is an MWE

julia> function makevec(ex)
           if ex.head == :call &&
           all(s -> s isa QuoteNode, ex.args[2:end])
               source = Expr(:vect, ex.args[2:end]...)
               fun = ex.args[1]
           
               quote 
               $source => ($fun)
               end
           end
       end;

julia> macro makevec(ex)
       esc(makevec(ex))
       end;

julia> @makevec :x + :y
[:x, :y] => (+)

julia> @makevec :x .+ :y
ERROR: UndefVarError: .+ not defined
Stacktrace:
 [1] top-level scope
   @ REPL[37]:8

julia> [:x, :y] => (.+)
[:x, :y] => Base.Broadcast.BroadcastFunction(+)

I'm not experienced enough with metaprogramming to know exactly at what stage Julia is testing for the existence of .+. However note that

julia> getproperty(Main, :.+)
ERROR: UndefVarError: .+ not defined

Any insights are appreciated!

cc @simeonschaub

@simeonschaub
Copy link
Member

simeonschaub commented Oct 26, 2020

The important thing to note here is that the identifier :.+ (== Symbol(".+")) is not the same thing as the standalone expression :(.+) (== Expr(:., :+)). a .+ b parses as Expr(:.+, a, b), but only :(.+) gets lowered to a call to Base.BroadcastFunction, which is why your example doesn't work. I am afraid changing anything about how we parse a .+ b would be too breaking in other places, though, so I don't think there's anything particularly actionable here, except for maybe documenting this potential gotcha a bit better.

A solution in your particular case would be to define something like:

normalize_f(f) = f isa Symbol && startswith(String(f), ".") ? Expr(:., Symbol(String(f)[2:end])) : f

and using that to normalize the first argument of call expressions.

@simeonschaub simeonschaub changed the title Macros not working with .* after #37583 infix .* parses differently than standalone .* Oct 30, 2020
@simeonschaub simeonschaub added the docs This change adds or pertains to documentation label Oct 30, 2020
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

2 participants