假设您具有以下功能
var action = (function () {
var a = 42;
var b = 2;
function action(c) {
return a + 4 * b + c;
}
return action;
}());
// how would you parse action into it's serialized LISP / AST format?
var parsed = parse(action);
是否有可能有一个函数引用该函数action
并输出 LISP 格式(lambda (c) (plus (plus 42 (multiply 4 2)) c))
我们被允许对action
可以做的事情进行一些限制。
- 正文应该只是一个表达式
- 它应该是一个纯函数
- 任何自由变量都是常数
主要问题是给定一个函数,您可以使用一系列输入调用它的源代码,您能否找到正确的值来替换自由变量?
对于上面的示例,您知道 a 和 b 是常数,您可以智能地绘制几个值的输出并查看模式,然后就知道常数是什么。
问题:
您将如何编写一个函数,该函数采用函数引用及其源代码,并为该函数生成某种形式的 AST,并用任何自由变量替换它们的运行时值。
AST 格式的一个示例是代码的 LISP 等价物。
我基本上想序列化和反序列化函数并让它表现相同
应该注意的是,如果传递{ a: a, b: b }
给分析函数,问题就会变得微不足道。那就是作弊。
用例:
我想生成一个与语言无关的纯 JavaScript 函数形式,这样我就可以有效地将它传递给 C++,而不需要我的库的用户使用 DSL 来创建这个函数
假设您有一个数据库驱动程序
var cursor = db.table("my-table").map(function (row) {
return ["foo", row.foo]
})
您想在运行时确定函数是什么并将其转换为 AST 格式,以便您可以使用高效的查询构建器将其转换为 SQL 或数据库具有的任何查询引擎。
这意味着您不必编写:
var cursor = db.table("my-table").map(function (rowQueryObject) {
return db.createArray(db.StringConstant("foo"), rowQueryObject.getProperty("foo"))
})
这是 DB 库可以使用查询对象执行的功能,让您无需冗长的方法即可构建查询对象转换。