Javascript中的模式匹配表达式

时间:2018-11-30 11:50:53

标签: javascript functional-programming

我正在通过JS中的函数式编程进行工作。最近,我开始使用Daggy来完成简单的模式匹配,但是我认为我并没有完全理解它。

给出以下代码:

  if(a === 1 && !b) {
   do(y)
  }

   if(b === 3 && c === 2) {
    do(z)
  }

  if (a) { 
    do(x) 
  }

有没有办法将这种凝聚力提高到类似的水平?

   when [a === 1 && !b] : do(y)
   when [a] : do(x)
   when [b === 3 && c === 2]: do(z)

3 个答案:

答案 0 :(得分:2)

JavaScript可能没有您正在谈论的模式匹配。有an active proposal使用case / when进行添加,这是该提案的示例:

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)
  }
}

它目前仅处于the process的第1阶段,因此它可能不会进行,可能会在进行之前发生根本性的变化,并且可能需要数年的时间才能完成各个阶段并使用该语言。 Babel plugin上有工作。

不过,恐怕我现在还不清楚如何将其应用于您的示例,因为它似乎想要case的操作数。

同时,如果您想要的是简洁感,那么一系列if / else if可能会非常简洁:

if (a === 1 && !b)           foo(y);
else if (a)                  foo(x);
else if (b === 3 && c === 2) foo(z);

或者JavaScript的switch非常灵活(它实际上只是编写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;
}

(我不主张这样做,只是指出这是一种选择。)

答案 1 :(得分:0)

您可以为数据创建包装器类,然后使用函数检查条件,并在满足特定条件的情况下采取措施。

简单易用,没有任何库。

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')
  );

答案 2 :(得分:0)

确定Daggy可以定义Maybe

    const Maybe = daggy.taggedSum('Option', {
        Just: ['a'],
        Nothing: []
    })

然后在其上定义名为alt的原型函数,该函数基本上可以回退到传递的值

    // alt :: Alt f => f a ~> f a -> f a
    Maybe.prototype.alt = function(o): Maybe<T> {
        return this.cata({
          Just: _ => this,
          Nothing: () => o
        })
      }

因此,我们可以进行一些模式匹配或类似的操作

    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))