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

Have variables consistent by default outside slurps #5

Open
fcard opened this issue Jul 30, 2015 · 3 comments
Open

Have variables consistent by default outside slurps #5

fcard opened this issue Jul 30, 2015 · 3 comments

Comments

@fcard
Copy link
Owner

fcard commented Jul 30, 2015

The main reason I made consistency optional is because of slurps, because when one writes (*{x},), they probably mean a tuple of any sequence of elements, not a sequence of the same element. However, when one writes (x,x), they likely mean a tuple of two of the same element, so maybe it's best to have consistency be the default outside slurps, and nonconsistency on the inside.

@fcard
Copy link
Owner Author

fcard commented Aug 1, 2015

Maybe a better solution would be to have variables inside slurps match the entire sequence of values rather than each individually, e.g. Given the expression (1,1,1), x in (*{x},) matches [1,1,1], rather than 1 three times. That would make it consistent with destructuring. Then I could change the meaning of :C{x} to "sequence of the same element", or maybe just remove it, I don't know whether that's useful enough to have special syntax.

fcard added a commit that referenced this issue Aug 12, 2015
This will make consistent variables the default. Also, variables in
slurps are matched with the sequence of arguments rather than each
individually (as described in #5)

This should allow destructuring to use the captured values rather than
having to walk the pattern tree again, <s>hopefully making the process
faster</s> this is currently slower, but can be made faster.
@fcard
Copy link
Owner Author

fcard commented Aug 12, 2015

Mostly done, but :(*{x},*{x}), which would match :(1,2,1,2), :(a,b,c,a,b,c), etc, doesn't work yet.

@fcard
Copy link
Owner Author

fcard commented Mar 8, 2017

Time to try fixing this.
For reference, the current algorithm first scans the whole sequence to determine ranges for the slurps.

sequence: :[(1,2),(3,4),(5,6),7,8,9,10]
pattern: [*{(x,y)}, a, *{z}, 10]

range for pattern 1: 1:3
range for pattern 2: 4:5

Only then does it start putting values into the variables, in a manner that simplified would look like this:

vars[:x] = []
vars[:y] = []
for i in 1:3
  push!(vars[:x], sequence.args[i].args[1])
  push!(vars[:y], sequence.args[i].args[2])
end

vars[:z] = []
for i in 5:6
  push!(vars[:z], sequence.args[i])
end

Since extracting the values is almost always the costliest part, it's very handy to only have to do once it as all the backtracking because of failed matches occurred in the "finding the ranges" part. However, once we have the same variable in different slurps, the actual values of the variables would start interfering with the ranges. It's possible to solve this more or less:

pattern: [*{x},*{x}]
sequence: :[1,2,1,2]

attempted range for 1: 1:4
attempted range for 2: []
#--ranges are not the same size, backtrack...
attempted range for 1: 1:3
attempted range for 2: 4:4
#--ranges are not the same size, backtrack...
attempted range for 1: 1:2
attempted range for 2: 3:4
#--ranges are the same size, proceed

Then we extract the values of the first one, and on the subsequent ones
we just compare to see if they are equal and fail the match otherwise.

function extract_simple(vars, range, name, seq)
  if haskey(vars, name)
    action = (v,i) -> (vars[name][i-start(range)+1] == v)
  else
    vars[name] = []
    action = (v,i) -> (push!(vars[name], v); true)
  end

  for i in range
    action(seq[i], i) || return false
  end
  return true
end

extract_simple(vars, 1:2, :x, :[1,2,1,2].args) || return false
extract_simple(vars, 3:4, :x, :[1,2,1,2].args) || return false
return true

I am thinking of cases where this might fail... (Also I just found a bug in the *normal* algorithm so I need to fix that first)

The whole thing is due to a rewrite anyway, looking back 2 years after it's much more messy and harder to follow than any of the other code, which I still can read pretty easily even after all this time (go past me! Other then this slurp thing!)

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

No branches or pull requests

1 participant