Skip to content

Instantly share code, notes, and snippets.

@renanpvaz
Last active April 14, 2019 23:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save renanpvaz/204621617e5297d6c8342f67990a490e to your computer and use it in GitHub Desktop.
Save renanpvaz/204621617e5297d6c8342f67990a490e to your computer and use it in GitHub Desktop.
JavaScript function pattern matching inspired by Haskell's
f = (...fns) => {
const [main, ...variations] = fns.reverse()
const ƒunction = (...appliedArgs) => {
const variation = variations.find(
args => appliedArgs.every(
(appliedArg, i) => args.slice().splice(0, args.length - 1)[i] === appliedArg
)
)
if (variation) {
return variation.slice(-1)[0](...appliedArgs)
} else {
return main.call(ƒunction, ...appliedArgs)
}
}
return ƒunction
}
luck = f(
[7, () => 'LUCKY NUMBER SEVEN'],
() => 'Sorry, you\'re out of luck, pal!'
)
luck(7)
// "LUCKY NUMBER SEVEN"
luck(1)
// "Sorry, you\'re out of luck, pal!"
// if the function is recursive:
fibonacci = f(
[0, () => 0],
[1, () => 1],
n => fibonacci(n - 1) + fibonacci(n - 2)
)
fibonacci(0)
// 0
fibonacci(1)
// 1
fibonacci(7)
// 13
factorial = f(
[0, () => 1],
n => n * factorial(n - 1)
)
@A1rPun
Copy link

A1rPun commented Apr 10, 2019

👏 👏 Very clever setup! I like it

EDIT:
I tried to do something like this but it won't work with dynamic arguments.

fibonacciTail = f(n => fibonacciIter(n, 0, 1));
fibonacciIter = f(
  [0, (_n, prevFib, _fib) => prevFib],
  [1, (_n, _prevFib, fib) => fib],
  (n, prevFib, fib) => fibonacciIter(n - 1, fib, prevFib + fib)
);

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