estree 传送器
ESTree AST Transversal作为访客的替代品.
JavaScript 中的传送器
转换器的首要目标是运行一个输入的转换管道 不创建中间值的数值流。 描述 计算是脱钩的,因此使程序设计更加清洁和容易 开发和维护.
这种脱钩的设计在jquery之后可能流行于JavaScript 图书馆。 其他图书馆也采用了类似的工具 也变得很受欢迎。 以下是将两个计算与 jquery 映射函数数字 :
store(produce().map(f).map(g))
实例 produce 可能读取一些大文件并将读取值存储于 a
j 查询对象。 虽然 store 将计算值存储到另一个文件中.
每个函数都可以去掉或给集合添加几个新元素.
首先它运行 f 函数在整个收藏和存储中间
生成内存, 运行后 g 誓以报应
是在内存中,只有在最终结果被存储成文件之后。 对大或
这可能甚至无限的溪流 这显然是不可接受的.
这项任务经常发生,有许多解决办法。 举个例子
节点流和 pipe 操作将流变压器添加到其它一些
流线。 或克洛朱尔传导器(与图书馆使用过的东西不同)
与JS的几个港口一样
传导器-js
或进入 兰达。 。 。 .
克洛朱尔出纳器改变消费者(称为降低克洛朱尔的功能), 而这个图书馆的转录器 改造制作人, 这是基本的 使得这些转录器更容易在联署材料中定义和使用。 制作 并结合转导器 成为简单的JS编程任务 不需要研究 其他图书馆接口协议。 这里可以使用联署材料的许多部分,例如: ES6 生成器功能或不同的控制语句, 包括:.
以下是转录器映射流值的例子.
function map(fun) {
return function*(input) {
for(const i of input) {
yield fun(i)
}
}
}
它与jquery 映射不同,因为它不能去除或替换单个元素
少了几个,但很显然 如何制造出类似的小转录器
执行这些任务。 完全不需要制造通用转录器。 也许
具体执行具体任务的机构。 只读了一到几个
输入延时器 for-of 或带有 next,计算某物,存储电流
在本地变量中状态,并发送输出值为 yield 表达式。 没错
仍然很容易与一些其他的传译者一起完成另一部分工作.
除非一些转录器有意缓冲输入值,否则任何输入都无法存储
在记忆中.
有一篇关于转导器改造生产商的论文(如本图书馆): Lazy v. Yield: 递增型,线性型 漂亮印刷 从2012年起(第一次提到cljure transcer(转换消费者)是 也许这个2014年 博客文章。 。 。 . 在纸上,转录器用来确保线性复杂 用于漂亮打印 带有类似此库使用的分级文档编码.
使用从纸张流中生成的值的术语 生产商。 。 。 .
例如它是一个生成器函数, 从信道读取数据并返回
块与 yield 表达式。 也许只是一些 Array 转至
输入转录器管道或任何可活性的东西.
计算结果转给 消费者 函数. Array.from 这是其中之一
此函数。 它只是将所有产生的值写入记忆中数组.
这也可能是一个函数将值写入信道.
使用辅助功能的操纵库,如 Ramda 制造和操纵这种传导器更为简单。 举个例子 烟斗 函数构成导出器 单一,因为转接器只是功能.
以下是使用 Ramda 写的 jquery 示例 pipe数字 :
consume(R.comp(map(f),map(g))(produce()))
接下来是绝对相同的:
consume(map(R.comp(f,g))(produce()))
即无中间值,执行 f 财务报告和审定财务报表 g 为每个元素互开
输入延时器.
AST 转接器
与AST流不同的是,AST是分级的,但我们仍然可以将其转化为序列. 对于 复杂节点会发出开始和结束的值 儿童在两者之间。 这是 与游客非常相近,其价值等级被平整为相应的 处理者呼叫。 因此,转接器和访客 与内部和 外道传行者.
图书馆不出口任何转出器,只出口生产商和消费者 函数:
produce- 取 AST 节点并返回 AST 转盘事件consume-取出溪流,从中建立AST节点
还出口 Tag 默认 AST 字段和类型名称的对象.
通话 consume 如果AST更新到位,则可能没有必要
这也许不是一个好主意.
事件流是一个有以下字段的对象:
enter- 布尔显示曲面进入节点leave- 布尔显示转弯出入口节点value- 原AST节点值在node字段,这是 共享enter财务报告和审定财务报表leave。 。 。 .pos- 球场的名称,它不是一个字符串,但 特殊标记值,默认标记为 内Tag库导出地图type- 节点类型标记,例如:pos
如果是没有孩子的节点 enter 财务报告和审定财务报表 leave 两者都是真实的.
以下是可变值替代转录器的例子.
function* subst(dict, s) {
for(const i of s) {
switch (i.type) {
case Tag.Identifier:
const n = dict[i.value.node.name]
if (n) {
if (i.enter)
yield* produce(n,i.pos)
continue
}
break
case Scope:
if (i.enter) {
dict = Object.create(dict)
for (const j in i.value)
dict[j] = false
} else
dict = Object.getPrototypeOf(dict)
break
}
yield i
}
}
这是相当简单和可以理解的。 对参观图书馆没有了解
需要协议。 例如,顶站迭代访客通常需要
以某种方式发出信号,例如,对函数结果具有特殊价值.
在这里,它只是普通的杰瓦克语 break 语句.
特殊节点类型( N)Scope) 这里处理的是同名变量,但
在子函数定义中定义。 如果我们不想碰它们,我们可能会跑
范围计算 转出器之前,注射此类 Scope 节点。 他们会的
被忽略 consume 函数.
使用非常简单, 例如重命名 i 变量改为“j”:
consume(subst({i:{type:"Identifier", name: "j"}}, scope(produce(ast))))
或更清洁与拉姆达:
R.pipe(
produce,
scope,
subst({i:{type:"Identifier", name: "j"}}),
consume
)(ast)
更多细节 测试/重命名.js
自由主义
根据麻省理工学院(麻省理工学院)许可证的规定分发.