考虑这个 Lisp 宏:
(defmacro doif (x y) `(if ,x ,y))
在 Haskell 中也是如此:
doif x y = if x then (Just y) else Nothing
是否有可能在 JavaScript 的“lisp-y”语言中实现这种优雅?(“lisp-y”一词的使用来自JS语言的作者)
考虑这个 Lisp 宏:
(defmacro doif (x y) `(if ,x ,y))
在 Haskell 中也是如此:
doif x y = if x then (Just y) else Nothing
是否有可能在 JavaScript 的“lisp-y”语言中实现这种优雅?(“lisp-y”一词的使用来自JS语言的作者)
对的,这是可能的。如果您只是想要 lisp-y 代码的一对一映射,那么您可以使用条件运算符,如下所示:
x ? y : null // note that x and y are expressions, not values: they aren't eval'd
如果您不介意表达式的结果是假值(而不是显式null
值),那么您可以使用保护 运算符:
x && y // reminder: x and y are expressions - they aren't evaluated until needed
如果您想创建自己的doif
语法,则可以使用sweet.js提供的卫生宏,如下所示:
macro doif {
rule { ($x:expr) ($y:expr) } => { $x ? $y : null }
}
上面的宏允许您编写如下代码:
doif (x < 100) (x + 1)
上面的代码被转换为:
x < 100 ? x + 1 : null
当使用这些运算符中的任何一个时,如果条件x
为假y
,则不计算。
您可以在 Javascript 中实现宏,因为编译器是运行时的一部分(您可以eval
使用字符串并获取代码)。然而,要接近 Lisp,您需要实现自己的完整语言,因为eval
只能生成完整的函数,而不是表达式。
相反,如果您只是考虑延迟评估,则可以通过将代码包装在闭包中来轻松完成:
function my_if(condition, then_part, else_part) {
return condition ? then_part() : else_part();
}
my_if(foo < bar,
function(){ return bar -= foo; },
function(){ return foo -= bar; });
当然,您也可以创建一个闭包,通过延迟测试来封装整个操作......
function my_if(condition, then_part, else_part) {
return function() {
return condition() ? then_part() : else_part();
}
}
var my_prog = my_if(function(){ return foo < bar; },
function(){ return bar -= foo; },
function(){ return foo -= bar; });
my_prog(); // executes the code
我想在非惰性语言中模拟惰性的常用方法是手动 thunkify。我对Javascript不是很了解,所以我打算改写伪代码,希望大家能把Javascript的语法画在idea上。
function doif(x, y) {
if(x) { return y(); }
else { return undefined; }
}
和一个示例电话:
function expensive() {
// do a lot of work here
}
doif(false, expensive); // runs very fast
doif(true , expensive); // runs very slow
doif(true , expensive); // runs very slow (unlike Haskell, but I think like Lisp)