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

Union problem in @capture #40

Closed
aytekinar opened this issue May 3, 2017 · 5 comments
Closed

Union problem in @capture #40

aytekinar opened this issue May 3, 2017 · 5 comments

Comments

@aytekinar
Copy link

Hey! I was playing with the package and I spotted a problem while trying unions in @capture:

julia> using MacroTools

julia> versioninfo()
Julia Version 0.5.1
Commit 6445c82d00 (2017-03-05 13:25 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-3720QM CPU @ 2.60GHz
  WORD_SIZE: 64
  BLAS: libopenblas (NO_AFFINITY SANDYBRIDGE)
  LAPACK: liblapack
  LIBM: libm
  LLVM: libLLVM-3.7.1 (ORCJIT, ivybridge)

julia> macro m1(ex)
         @capture(ex, f_(args__) = body_ | function f_(args__) body_ end) || return ex
         @show f
         @show args
         @show body
         return ex
       end;

julia> macro m2(ex)
         @capture(ex, (f_{T_}|f_)(args__) = body_) || return ex
         @show f
         @show args
         @show body
         return ex
       end;

julia> macro m3(ex)
         @capture(ex, f_(args__) = body_) || @capture(ex, function f_(args__) body_ end) || return ex
         @show f
         @show args
         @show body
         return ex
       end;

julia> @m1 f(x) = 5x;
f = :f
args = Any[:x]
body = :(5x)

julia> @m1 function f(x) 5x end;
WARNING: Method definition f(Any) in module Main at REPL[6]:1 overwritten at REPL[7]:1.

julia> @m2 f(x) = 5x;
f = :f
args = Any[:x]
body = quote  # REPL[8], line 1:
    5x
end
WARNING: Method definition f(Any) in module Main at REPL[7]:1 overwritten at REPL[8]:1.

julia> @m3 f(x) = 5x;
f = :f
args = Any[:x]
body = quote  # REPL[9], line 1:
    5x
end
WARNING: Method definition f(Any) in module Main at REPL[8]:1 overwritten at REPL[9]:1.

julia> @m3 function f(x) 5x end;
f = :f
args = Any[:x]
body = quote  # REPL[10], line 1:
    5x
end
WARNING: Method definition f(Any) in module Main at REPL[9]:1 overwritten at REPL[10]:1.

Even though m1 and m2 are copies from README, they don't work properly. I hope I am not missing some stupid mistake while trying.

I'd appreciate if you could help. Thanks!

@aytekinar
Copy link
Author

Same goes for the other example... When I change the order in (f_{T_}|f_)(args__) = body_, I have problems:

macro m2(ex)
  if @capture(ex, (f_{T_}|f_)(args__) = body_)
    @show f
    @show T
    @show args
    @show body
  end
  return ex
end

@m2 f(x) = 5x
@m2 f{T}(x::T) = 3x

macro m3(ex)
  if @capture(ex, (f_|f_{T_})(args__) = body_)
    @show f
    @show T
    @show args
    @show body
  end
  return ex
end

@m3 f(x) = 5x
@m3 f{T}(x::T) = 3x

macro m4(ex)
  if @capture(ex, ((f_)(args__) = body_) | ((f_{T_})(args__) = body))
    @show f
    @show T
    @show args
    @show body
  end
  return ex
end

@m4 f(x) = 5x
@m4 f{T}(x::T) = 3x

I cannot understand where I am doing a mistake. @m3 and @m4 do not work as intended.

@MikeInnes
Copy link
Member

f_(args__) = body_ | function f_(args__) body_ end gets parsed as f_(args__) = (body_ | function f_(args__) body_ end) so that's causing one issue. The other stuff seems to be working for me:

julia> @capture(:(f(x) = 5x), (f_{T_}|f_)(args__) = body_)
true

julia> @capture(:(f{T}(x) = 5x), (f_{T_}|f_)(args__) = body_)
true

Are these definitely not working for you?

@aytekinar
Copy link
Author

Your examples do work. Now I get the point --- sorry! In the very first version, as you have pointed out, lack of parenthesis was causing the headache. Then, when I change the order of (f_{T_}|f_) in your example to (f_|f_{T_}), the second one never gets triggered. Apparently, | in the macro is short circuit --- I had expected it to evaluate the right-hand side and give me the more specialized solution when one defines f{T}(x::T) = 3x in the expression. However, f_ catches them all.

Thanks for the answer!

@rjplevin
Copy link

I'm having a similar problem, but it shows up only if I restrict the type to match and use "|":

Main> ex = @MacroTools.q ext_var1[2010:2049, (US, CHI)] = name1
:(ext_var1[2010:2049, (US, CHI)] = name1)

# Works without specifying Symbol type
Main> @capture(ex, extvar_  = rvname_)
true

# Captures a symbol
Main> rvname
:name1

# Works with Symbol type without "|"
Main> @capture(ex, extvar_  = rvname_Symbol)
true

# Works with "|" without Symbol type
Main> @capture(ex, (extvar_ = rvname_) | (extvar_ += rvname_))
true

# Fails with "|" and Symbol type
Main> @capture(ex, (extvar_ = rvname_Symbol) | (extvar_ += rvname_))
false

# Just for completeness:
Main> @capture(ex, (extvar_ = rvname_) | (extvar_ += rvname_Symbol))
true

@cstjean
Copy link
Collaborator

cstjean commented Mar 30, 2022

Closing, as the original question was answered. Filed new issue in #180

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants