简体   繁体   English

Javascript 中的模式匹配表达式

[英]Pattern matching expressions in Javascript

Im making my way throught functional programming in JS.我正在通过 JS 进行函数式编程。 Recently I started to use Daggy to accomplish simple pattern matching, but I don't think that I fully get it.最近开始用Daggy来完成简单的模式匹配,但是我觉得还没有完全搞定。

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)

JavaScript doesn't have the kind of pattern matching you're probably talking about. JavaScript可能没有您正在谈论的那种模式匹配。 There is an active proposal to add it using case / when , here's an example from that 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)
  }
}

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. 不过,它目前仅处于流程的第1阶段,因此它可能不会进行,可能会在进行之前发生根本性的变化,并且可能需要数年的时间才能完成各个阶段并使用该语言。 There's work on a Babel plugin . 有一个Babel插件的工作。

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

In the meantime, a series of if / else if can be fairly terse if terseness is what you're looking for: 同时,如果您正在寻找简洁,则一系列if / else if可能会相当简洁:

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 ): 或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;
}

(I'm not advocating it, just pointing out it's an option.) (我不主张这样做,只是指出这是一个选择。)

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

Sure with Daggy you could define Maybe 当然,有了Daggy,您可以定义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 :: 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))

Developer and maintainer of Patroon. Patron 的开发者和维护者。 I was looking for js style pattern matching and had to build my own.我一直在寻找 js 风格的模式匹配,不得不自己构建。 This is what your example would look like using the patroon library:这是您的示例使用 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/patroon https://github.com/bas080/patron

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

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