Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用JavaScript重构这个Lisp和Haskell风格的宏_Javascript_Haskell_Lisp - Fatal编程技术网

用JavaScript重构这个Lisp和Haskell风格的宏

用JavaScript重构这个Lisp和Haskell风格的宏,javascript,haskell,lisp,Javascript,Haskell,Lisp,考虑以下Lisp宏: (defmacro doif (x y) `(if ,x ,y)) 哈斯凯尔也是如此: doif x y=如果x那么(只有y)其他什么都没有 在JavaScript的“lisp-y”语言中有可能实现这种优雅吗?(单词“lisp-y”的用法来自JS语言的作者)我认为在非惰性语言中模拟惰性的通常方法是手动thunkify。我对Javascript不太了解,所以我将编写伪代码,希望您能在这个想法上绘制Javascript语法 function doif(x, y) {

考虑以下Lisp宏:

(defmacro doif (x y) `(if ,x ,y))
哈斯凯尔也是如此:

doif x y=如果x那么(只有y)其他什么都没有


在JavaScript的“lisp-y”语言中有可能实现这种优雅吗?(单词“lisp-y”的用法来自JS语言的作者)

我认为在非惰性语言中模拟惰性的通常方法是手动thunkify。我对Javascript不太了解,所以我将编写伪代码,希望您能在这个想法上绘制Javascript语法

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)

是的,这是可能的。如果您只想对lisp-y代码进行一对一的映射,则可以使用以下方法:

x ? y : null // note that x and y are expressions, not values: they aren't eval'd
macro doif {
    rule { ($x:expr) ($y:expr) } => { $x ? $y : null }
}
如果您不介意表达式的结果是falsy值(而不是显式的
null
值),那么您可以使用:

如果要创建自己的
doif
语法,则可以使用由提供的宏,如下所示:

x ? y : null // note that x and y are expressions, not values: they aren't eval'd
macro doif {
    rule { ($x:expr) ($y:expr) } => { $x ? $y : null }
}
上述宏允许您编写如下代码:

doif (x < 100) (x + 1)
doif(x<100)(x+1)
上述代码将转换为:

x < 100 ? x + 1 : null
x<100?x+1:null

如果条件
x
为falsy,则使用这些运算符时,将不计算
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; });
函数my\u if(条件,然后是部分,否则是部分){
返回条件?然后_part():否则_part();
}
我的如果(foo
当然,您也可以创建一个闭包,通过延迟测试来封装整个操作

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
函数my\u if(条件,然后是部分,否则是部分){
返回函数(){
返回条件()?然后_部分():否则_部分();
}
}
var my_prog=my_if(function(){return foo
如果
x
在javascript中是
true
的话,你想执行
y
吗?不,你不能得到这种优雅,因为JS既没有宏,也不是非严格的语言。请不要试图在JS中使用优雅这个词,它会导致抑郁;)@我不同意。JavaScript是一种非常优雅的语言。是的,它是不纯的,不像Haskell那样有代数数据类型或模式匹配。尽管如此,它仍然是一种非常强大的语言。JavaScript支持函数式、面向对象和过程式编程——三大编程风格。因此,您可以混合和匹配您喜欢的任何编程风格。此外,它还具有原型继承(我认为这是继承和代码重用的优雅解决方案)。此外,JS的学习曲线不像Haskell那样陡峭。顺便说一句,我也喜欢Haskell和FP。@AaditMShah:那只是我的经历:)。无论如何看看@6502:我同意。现在,您可以将Haskell、F#、Scala等编译为JS。JS运行时,像V8和各种Mozilla的猴子:)是令人惊奇的工具,但是他们必须考虑JS语言的语义,并且把他们的手绑在一起。看到然后就是DOM:)
x?y:null
与lisp代码不同。
x
y
可以是任何表达式(而不仅仅是一些持有值的变量),这基本上意味着x和y都将以这种形式得到“评估”。检查
x
@Ankur之前不计算
y
所需的条件运算符只计算其第二个和第三个参数中的一个,因此在这方面与lisp代码类似。@Ankur我不同意。在这种情况下,
x
y
不是变量。它们是任何表达式的占位符。这就是我提供宏定义
doif
的原因。如果您仔细查看,
x
y
属于
expr
类型(任何表达式)。在这两种情况下,表达式
y
仅在
x
为真时才计算。@Ankur如果您不相信我,请查看演示:1)
true?警报(“Hello World!”):null
(将警报
“Hello World!”
):2)
false?警报(“Hello World!”):null
(将不会警报
“Hello World!”
):我认为不必调用
y
。OP写了
doif x y=if x then(只是y)else Nothing
。因此,即使
y
是一个函数(很可能不是),它也只是被包装在一个
值中。从来没有人叫过它。在我看来,正确的JavaScript转换是
x?y:null
@AaditMShah我对这个问题的理解是,我们希望将某个条件的计算延迟到以后(在本例中,“以后”是“在我们知道某个条件是否为真之后”)。将计算放在函数中是延迟它的一种方法,而调用函数是停止延迟的一种方法。如果
x
的计算结果为真实值,他只希望表达式返回
y
。例如,考虑下面的LISP代码:<代码>(DOIF(。这应该转化为
x<100?x+1:null
。把它翻译成
doif(x<100,function(){returnx+1;})
是不必要的样板。在任何一种情况下,第二个表达式仅在条件为truthy时计算,这就是为什么您可以执行类似于
条件的操作?警报(“你好,世界!”):null
警报
功能仅在
条件下调用