繁体   English   中英

Javascript 中的模式匹配表达式

[英]Pattern matching expressions in Javascript

我正在通过 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)

JavaScript可能没有您正在谈论的那种模式匹配。 一个积极的建议使用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)
  }
}

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

恐怕我现在还不清楚如何将其应用于您的示例,因为它似乎需要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;
}

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

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

简单易行,无需任何库。

 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 => da === 1 && !db, () => console.log('C1 => y') ) .when( d => db === 3 && dc !== 2, () => console.log('C2 => z') ) .when( d => da, () => console.log('C3 => x') ) .when( d => true, () => console.log('Last stop') ); 

当然,有了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))

Patron 的开发者和维护者。 我一直在寻找 js 风格的模式匹配,不得不自己构建。 这是您的示例使用 patron 库的样子:

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/patron

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM