3

考虑这个 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语言的作者)

4

3 回答 3

3

对的,这是可能的。如果您只是想要 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,则不计算。

于 2013-10-14T10:06:45.993 回答
1

您可以在 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
于 2013-10-14T20:20:19.530 回答
1

我想在非惰性语言中模拟惰性的常用方法是手动 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)
于 2013-10-14T09:58:06.320 回答