Skip to content

Instantly share code, notes, and snippets.

@wavebeem
Last active August 29, 2015 14:26
Show Gist options
  • Save wavebeem/c190d1b5ecab6ebaa0ac to your computer and use it in GitHub Desktop.
Save wavebeem/c190d1b5ecab6ebaa0ac to your computer and use it in GitHub Desktop.
Squiggle pattern matching idea
// map = fn(f, xs) match (xs) {
// case [] => []
// case [x, ...xs] => [f(x)] ++ map(f, xs)
// }
// This approach is going to be the best, but it requires the compiler to become
// aware of being inside functions, so it can expand things into statements,
// rather than being purely expression oriented. It's sort of amazing how far
// you can get only using expressions in JS, though. It will also need to
// rewrite variable usage, which might be a little tricky.
var map = function(f, xs) {
var $match1 = xs;
var $match1_x, $match1_xs;
if ($eq($match1, [])) {
return [];
} else if ($match1.length >= 1) {
$match1_x = $match1[0];
$match1_xs = $match1.slice(1);
return $plus$plus([f($match1_x)], map(f, $match1_xs));
} else {
throw new Error("match fail");
}
}
// This approach should allow for a clean "attempt to give me bindings, but
// allow for failed matches easily". "match" would return an object {ok: true,
// bindings: [...]} or simply {ok: false}. There could be nested accumulation
// of bindings, with a "throw" happening deep within, causing the top level to
// catch it and return {ok: false}. Maybe a little *gross*, but it would allow
// short, readable code, probably.
var map = function(f, xs) {
return (function(xs) {
var $_test = false;
$_test = $match(xs, ...);
if ($_test.ok) {
return (function() {
return [];
}($_test.values));
}
$_test = $match(xs, ...);
if ($_test.ok) {
return (function(x, xs) {
return [f(x)] ++ map(f, xs);
}($_test.values));
}
}());
};
# not sure if i want "=>" or "then" or something.
match (data) {
# arrays strictly match the number of elements provided --- no more, no less
case [x] => 1
case [_, y] => 2
case [x, ...xs] => "more"
# it's ok if objects have more keys you don't mention!
case {"length": n} => n
# shorthand for same key and binding name
case {length} => length
# if you want to assert more elements exist but ignore their values...
case {"foo": _, "bar": _, baz} => baz
# maybe % is some match suffix that asserts a predicate function passes?
# could be any user defined function in scope.
# this one i'm not as sure about
case x % isNumber => x
# you can nest expressions, of course!
case [{"name": n1}, {"name": n2}] =>
"Hello " ++ n1 ++ " and " ++ n2 ++ "!"
case "hello" => "world"
case 0 => "zero"
case 1 => "one"
# match will throw if no cases hold, so it's idiomatic to provide a catch-all fallback when appropriate.
case _ => "no match"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment