natefaubion / sparkler

Native pattern matching for JavaScript
MIT License
694 stars 18 forks source link

Pattern matching for Iterators #12

Open considerate opened 10 years ago

considerate commented 10 years ago

After reading a bit on ES-Discuss it seems as though the spread operator for iterator always should give an array as a result.

That basically makes it impossible to use an iterator over an infinite list (such as the fibonacci sequence) as a pattern. In order to be compliant with ES6 and still support iterators as a pattern may I suggest that we use a pattern with a syntax inspired by languages like Prolog, Erlang or Haskell.

I think the : operator might be good to use as the | operator is used for bitwise or and therefore matches as a part of an expression.

Proposal:

function* listWork {
   (x:xs) => {yield f(x); yield* listWork(xs);},
   (x:y:rest) => {yield f(x)+f(y); yield* listWork(xs);}
}

Where (x:xs) is desugared into:

let x = iter.next().value;
let xs = iter;

Also for symmetry in the syntax I really think it would be awesome to have an expression sugar for $(yield $x:expr;) ... yield* $xs:expr; of the same form (x:y:z:xs) in the function body. That is, having the above desugared into:

yield x;
yield y;
yield z;
yield* xs;

However, I am not sure that this would be possible to achieve as there is no keyword to match the macro on other than function or maybe the : token as an infix macro or operator.

Example:

function* listWork {
  (x:xs) => f(x) : listWork(xs),
  (x:y:rest) => f(x) + f(y) : listWork(rest)  
}

Note: Optionally [x:xs] might be used to match the iterators.

natefaubion commented 10 years ago

The reason you can't pattern match on iterators is because they are stateful. They don't let you view the data without consuming the iterator. Say I match 1:2:3 to pull 3 numbers out of an iterator. What happens if the iterator gives me 1:2:4 instead, failing the pattern match? I can't rewind the iterator and try the next branch.

natefaubion commented 10 years ago

On the topic of extending the pattern grammar, that's something I'd like to open up as sweet.js gets better module support. I'd like for other macro modules to be able to declare new pattern syntax and the logic that goes into matching it.