我将编译器从函数式语言编写到JS。编译器将在浏览器中运行。我需要在JS中实现模式匹配机制,因为原始语言有一个。我找到了Sparkler和Z。据我所知,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 ]) => {...}
)
}
如何正确展开这种模式匹配到ifs
和ors
?
答案 0 :(得分:1)
有一个proposal for Pattern Matching in ECMAScript,但截至2018年,它还处于初期阶段。
目前,“实施”部分仅列出:
- Babel Plugin
- Sweet.js macro(注意:这不是基于提案,此提案部分基于此提案!)
使用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
,您可以编写如下示例。您需要使用软件包随附的占位符名称(_
,A
,B
,C
,... 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 上发布。