Reputation: 370
Im making my way throught functional programming in JS. Recently I started to use Daggy to accomplish simple pattern matching, but I don't think that I fully get it.
Given this code:
if(a === 1 && !b) {
do(y)
}
if(b === 3 && c === 2) {
do(z)
}
if (a) {
do(x)
}
Is there a way to improve this cohercions into something similar to?:
when [a === 1 && !b] : do(y)
when [a] : do(x)
when [b === 3 && c === 2]: do(z)
Upvotes: 0
Views: 285
Reputation: 469
Developer and maintainer of Patroon. I was looking for js style pattern matching and had to build my own. This is what your example would look like using the patroon library:
const isNil = x => !(x != null)
patroon(
{a: 1, b: isNil}, y,
{b: 3, c: 2}, z,
{a: _}, x
)({a, b, c})
https://github.com/bas080/patroon
Upvotes: 0
Reputation: 61
Sure with Daggy you could define Maybe
const Maybe = daggy.taggedSum('Option', {
Just: ['a'],
Nothing: []
})
and then define a prototype function on it called alt
which can basically fallback to the passed value
// alt :: Alt f => f a ~> f a -> f a
Maybe.prototype.alt = function(o): Maybe<T> {
return this.cata({
Just: _ => this,
Nothing: () => o
})
}
So with it we can do some pattern matching or similar
function match(comparator, res) {
switch (comparator()) {
case true: return Maybe.of(res)
case false: return Maybe.Nothing
default: return Maybe.Nothing
}
}
MaybeF.Nothing
.alt(match(() => a === 1 && !b, () => y))
.alt(match(() => a, () => x))
.alt(match(() => b === 3 && c === 2, () => z))
Upvotes: 0
Reputation: 1560
You can create a wrapper class to your data and then use functions to check the conditions and do an action in case that the particular condition meets.
Simple and easy, without any libraries.
class typeWrap {
constructor(obj) {
this.var = obj;
this.done = false;
}
when (condition, doFn) {
if (!this.done && condition(this.var)) {
this.done = true;
doFn(this.var);
}
return this;
}
}
const data = new typeWrap({
b: 3, c : 9
});
data
.when(
d => d.a === 1 && !d.b,
() => console.log('C1 => y')
)
.when(
d => d.b === 3 && d.c !== 2,
() => console.log('C2 => z')
)
.when(
d => d.a,
() => console.log('C3 => x')
)
.when(
d => true,
() => console.log('Last stop')
);
Upvotes: 0
Reputation: 1074276
JavaScript doesn't have the kind of pattern matching you're probably talking about. There is an active proposal to add it using case
/when
, here's an example from that proposal:
const res = await fetch(jsonService)
case (res) {
when {status: 200, headers: {'Content-Length': s}} -> {
console.log(`size is ${s}`)
}
when {status: 404} -> {
console.log('JSON not found')
}
when {status} if (status >= 400) -> {
throw new RequestError(res)
}
}
It's currently just at Stage 1 of the process, though, so it may not proceed, may change radically before proceeding, and may take years to work through the stages and get into the language. There's work on a Babel plugin.
I'm afraid it's not immediately clear to me how I'd apply it to your example, though, as it seems to want an operand for case
.
In the meantime, a series of if
/else if
can be fairly terse if terseness is what you're looking for:
if (a === 1 && !b) foo(y);
else if (a) foo(x);
else if (b === 3 && c === 2) foo(z);
Or JavaScript's switch
is unusually flexible (it's really just another way to write if
/else if
):
switch (true) {
case a === 1 && !b: foo(y); break;
case a: foo(x); break;
case b === 3 && c === 2: foo(z); break;
}
(I'm not advocating it, just pointing out it's an option.)
Upvotes: 3