JavaScript中的函数式编程样式模式匹配

时间:2018-05-21 16:18:04

标签: javascript algorithm functional-programming compiler-construction pattern-matching

我将编译器从函数式语言编写到JS。编译器将在浏览器中运行。我需要在JS中实现模式匹配机制,因为原始语言有一个。我找到了SparklerZ。据我所知,Sparkler无法在浏览器中执行,Z也没有我需要的所有可能性。

所以我的语言有这样的语义:

count x []         <- 0
count x [ x : xs ] <- 1 + count x xs
count x [ y : xs ] <- count x xs

这是在此代码段中发生的事情:

第一行是函数的定义,它接受两个参数:一些变量x和空列表,并返回零。

第二行是函数的定义,它还有两个参数:一些变量x和list,以x开头,然后返回1 + count(x, xs)

这个例子我想生成这样的代码:

const count = (x, list) => {
    match(x, list) => (
        (x, []) => {...}
        (x, [ x : xs ]) => {...}
        (x, [ y : xs ]) => {...}
    )
} 

如何正确展开这种模式匹配到ifsors

3 个答案:

答案 0 :(得分:1)

一般情况

有一个proposal for Pattern Matching in ECMAScript,但截至2018年,它还处于初期阶段。

目前,“实施”部分仅列出:

  

列出案例

使用destructuring assignment,例如:

const count = list => {
  const [x, ...xs] = list;
  if (x === undefined) {
    return 0;
  } else if (xs === undefined) {
    return 1;
  } else {
    return 1 + count(xs);
  }
}

答案 1 :(得分:0)

使用ex-patterns,您可以编写如下示例。您需要使用软件包随附的占位符名称(_ABC,... Z),但可以重命名具有解构功能的回调函数中的匹配变量(包含所有命名匹配项的对象将作为回调函数的第一个参数传入。)

import { when, then, Y, _, tail, end } from 'ex-patterns';

const count = list => (
    when(list)
        ([], then(() => 0))  // match empty array   
        ([_], then(() => 1))  // match array with (any) 1 element      
        ([_, tail(Y)], then(({ Y: xs }) => 1 + count(xs)))  // match array and capture tail              
    (end);
);

这也涵盖了list = [undefined, 'foo', 'bar']的情况,我认为不会被接受的答案所涵盖。

要使代码更高效,可以使用Immutable.js count而不是数组来调用List(不需要更改)。在这种情况下,不需要在每个循环中将数组的tail部分切片并复制到新数组中。

与您提到的软件包一样,它并不是在浏览器中本机运行的,但是我想这并不是现代捆绑工具的主要障碍。

以下是文档:https://moritzploss.github.io/ex-patterns/

免责声明:我是ex-patterns的作者:)

答案 2 :(得分:0)

我需要模式匹配,并做了一些对我有用的东西。

这是一个匹配数组的 toPairs([...]) 函数。

  const {patroon, _} = require('patroon');

  const toPairs = patroon(
    [_, _], ([a, b, ...c], p=[]) => toPairs(c, [...p , [a, b]]),
    _, (_, p=[]) => p,
  )

https://github.com/bas080/Patroon.js

一个poc;考虑在 npm 上发布。