6 ms·
Pattern matching would be a great addition to JS. I built a pattern matching library[1] with a very similar syntax back in 2015 (although I will be the first to
by cshepp 8y ago
Pattern matching would be a great addition to JS. I built a pattern matching library[1] with a very similar syntax back in 2015 (although I will be the first to admit that it's a naive implementation). It makes validating/traversing deeply-nested objects much less verbose. I'm excited to see where this proposal goes.
[1] https://github.com/cshepp/Kasai https://github.com/cshepp/Kasai
- m0meni 8y agoNice library! This actually looks great. The syntax is a bit noisey, but tbh not any more than the actual proposal.
- c0nfused 8y agoI rather like your syntax compared to the proposed version. It is less concise but must more consistent and parsable: return match(user, [ [{first: $, middle: $, last: $}, (f, m, l) => f + ' ' + m + ' ' + l], [{first: $, last: $} , (f, l) => f + ' ' + l], [_, 'unknown'] ]);
- sloanesturz 8y agoI think that this is not always guaranteed to work, because {first: $, middle: $, last: $} is the same as {first: $, last: $, middle: $} ... so calling Object.keys() is not necessarily going to use a consistent ordering. I think that is why they have to use the more verbose syntax in the other library. I think you could do something like: {first: $.0, middle: $.1, last: $.2}, (f, m, l) => ... pretty easily, though.
- simonbw 8y agoI believe in es6 Object literals are guaranteed to keep their ordering, and Object.keys() will iterate through them in the order defined.
- denpaDawn 8y agoThe ordering of Object.keys() is equal to insertion order of the keys into the object. So if you have an Object generation function, it can insert the keys in the proper order (and take advantage of stuff like v8 hidden classes) http://2ality.com/2015/10/property-traversal-order-es6.html http://2ality.com/2015/10/property-traversal-order-es6.html
- mpfundstein 8y agoShameless plug but here is my pattern machter [1] :D Example: // simple factorial const factorial = n => match(n) .when(0, 1) .otherwise(n => n * factorial(n - 1)); // walking a tree class Tree { constructor(left, right) { this.left = left; this.right = right; } } class Node { constructor(value) { this.value = value; } } const T = (l, r) => new Tree(l, r); const N = v => new Node(v); const walkT = t => match(t) .when(Node, v => console.log(v.value)) .when(Tree, t => { walkT(t.left); walkT(t.right)}) .otherwise(_ => 'error'); const mapT = (f, t) => match(t) .when(Node, v => N(f(v.value))) .when(Tree, t => T(mapT(f, t.left), mapT(f, t.right))) .otherwise(_ => { throw new Error('error') }); Works also on deeply nested objects. [1] https://github.com/MarkusPfundstein/pmatch-js https://github.com/MarkusPfundstein/pmatch-js
- cshepp 8y agoMethod-based syntax for pattern matching is easier to read and grok (IMO), but it lacks the dynamic capabilities of data-oriented syntax (in Kasai, patterns can be built/manipulated at runtime). It's interesting to compare the two approaches.
- mpfundstein 8y agoIf you mean by method-based pattern matching that you evaluate a function for each 'case'. My lib can do that do: const match = require('pmatch-js') const _ = require('lodash') const fizzbuzz = x => match(x) .when(a => a % 3 == 0 && a % 5 == 0, 'fizzbuzz') .when(a => a % 5 == 0, 'buzz') .when(a => a % 3 == 0, 'fizz') .otherwise(a => a) console.log( _.range(1, 101).map(fizzbuzz).join(' ') ) But maybe you mean something totally different :-) EDIT: Ah I think I know what you mean. Your lib takes an array of tuples to define the patterns. Sorry for the confusion.
- dkarbayev 8y agoWow, importing the whole lodash to use just one function? There’s es6 way of getting an array with a range of numbers: [...Array(100).keys()].map(v=>v+1) A little bit longer but no dependencies.