RelationalAI-oss / Rematch.jl

Pattern matching
Other
52 stars 6 forks source link

Match with already defined variables (ie constants) #5

Open programmeroftheeve opened 6 years ago

programmeroftheeve commented 6 years ago

It should be able to match with constants.

Example:

using Rematch
module Mod
    const VALUE = 0
end
import .Mod

const FOO = 1
const BAR = 2
const FOOBAR = 3
const BAR_FOO = 4

x = FOO

y = @match x begin
    Mod.VALUE => :mod_value
    FOO => :foo
    BAR => :bar
    FOOBAR => :foobar
    BAR_FOO => :barfoo
    _ => nothing
end

@assert y == :foo
mbravenboer commented 6 years ago

This sounds useful, but I'm not entirely sure that it can be implemented in a macro. We'd need to be able to reflect over what identifiers are in scope. Maybe @jamii can comment?

We could also introduce a specific syntax that identifies this, which would be a little more cumbersome to the user.

jamii commented 6 years ago

Basing it on scope would mean that compile order affects the results, which is probably unpleasant.

$FOO or ==(FOO) might work for syntax. Or you could match MacroTools and use _foo for variables.

mbravenboer commented 6 years ago

Thanks @jamii , makes sense.

ghost commented 5 years ago

I agree with Jamie that the dollar-sign syntax would seem to make sense here: you're simply using the name to refer to the value you want to match on. So I think interpolating is a good metaphor here.

It also matches what BenchmarkTools does for their macros:

@btime inv($A);           # we interpolate the global variable A with $A
@benchmark [i*i for i in $A]

https://github.com/JuliaCI/BenchmarkTools.jl#quick-start https://github.com/JuliaCI/BenchmarkTools.jl/blob/master/doc/manual.md#interpolating-values-into-benchmark-expressions

ghost commented 5 years ago

This was mostly fixed by https://github.com/RelationalAI-oss/Rematch.jl/pull/11.

@btaidm's original example can be matched like this:

julia> using Rematch

julia> module Mod
           const VALUE = 0
       end
>> Main.Mod

julia> begin
         const FOO = 1
         const BAR = 2
         const FOOBAR = 3
         const BAR_FOO = 4
       end
>> 4

julia> x = FOO
>> 1

julia> y = @match x begin
          $(Mod.VALUE) => :mod_value
          $FOO => :foo
          $BAR => :bar
          $FOOBAR => :foobar
          $BAR_FOO => :barfoo
          _ => nothing
       end
>> :foo

julia> @assert y == :foo
ghost commented 5 years ago

I'm leaving the Issue open because it still doesn't support interpolating splatted patterns, such as this:

julia> let arr=[10,20,30],  x=[1,2,3, 10,20,30, 5]
         @match x begin
               # splatting existing values
               [fronts..., $(arr...), back] => [fronts..., back]
         end
       end