【问题标题】:Getting reference to the JavaScript Function object behind an operator获取对运算符后面的 JavaScript 函数对象的引用
【发布时间】:2011-01-25 16:30:23
【问题描述】:

这是一个 lisp 过程,它简单地将 'a' 添加到 'b' 的绝对值:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

我认为这很漂亮,我正在努力寻找用 JavaScript 编写它的最佳方式。但是我的 JavaScript 代码并不漂亮:

var plus = function(a,b) {
    return a + b;
};

var minus = function(a,b) {
    return a - b;
};

var aPlusAbsB = function(a,b) {
    return (b > 0 ? plus : minus)(a,b);
}

主要问题是我不能使用 +- 符号作为对它们真正代表的函数的引用,就像我可以使用 lisp 一样。任何人都可以想出一个更优雅的方式来做这样的事情,还是我达到了语言边界?

显然,我可以这样做:

var aPlusAbsB = function(a,b) {
    return a + Math.abs(b);
}

,但这更像是一个思想实验,而不是一个务实的问题。

有什么方法可以让我引用 JavaScript 语言中的核心函数,就像它们是用户定义的一样?

【问题讨论】:

  • 您是否看过 Functional.js 及其将简单函数表示为字符串的古怪而可爱的语法?
  • 我也不知道内置算术运算符是否真的存在任何真正意义上的 Function 实例。
  • 我看过函数库,它看起来很酷。我只是想知道是否有任何方法可以仅使用核心 JS 来做到这一点。和@Pointy 我想知道同样的事情。它们可能不是 Function 对象,但其中的逻辑执行方式类似于函数的执行方式。
  • 嗯,我对这个问题很感兴趣,在学术上,但我从未见过任何让我认为某处有这样的 Function 对象的参考资料。然而,Javascript 总是令人惊奇。
  • @Pointy:我一直认为大多数算术运算符都是在 CPU 级别运行的。但这可能不适用于 JavaScript。

标签: javascript functional-programming lisp scheme


【解决方案1】:

这是一个非常酷的想法 - 非常适合评估数学表达式,但您根本无法将运算符(或其背后的逻辑)设置为变量。对不起:-)

【讨论】:

  • 看在 OP 的份上,我不想给你 +1,但这是真的,你无能为力。
  • @musicfreak: 哈哈,谢谢 ;-) 我经常想到这个,因为有时我不得不检查变量的状态来决定是 + 还是 -,但如果我可以直接通过 +- 会更酷 - 它会保存整个 if 语句!
  • 除非被一些 JavaScript 专家证明,否则这似乎是答案:(。
【解决方案2】:

这比你的建议稍微漂亮一些,但远不如你对这个概念的 lisp 表示漂亮:

var aPlusAbsB = function(a, b) {
    var plus = function(a, b) {
      return a + b;
    };
    var minus = function(a, b) {
      return a - b;
    };
    return (b > 0 ? plus : minus)(a, b);
}

这将等同于方案中的以下内容:

(define a-plus-abs-b
  (lambda (a b)
    (let ((plus (lambda (a b) (+ a b))) (minus (lambda (a b) (- a b))))
      (cond ((> b 0) (plus a b))
      (else (minus a b))))))

【讨论】:

    【解决方案3】:

    虽然不如 LISP 代码那么优雅,但您可以动态创建一个函数,该函数就像一个运算符(在数字上),但事实并非如此。

    function op(o) {
        return new Function("a", "b", "return a " + o + " b");
    }
    
    
    function aPlusAbsB(a, b) {
        return (b > 0 ? op('+') : op('-'))(a, b);
    }
    

    此外,我们可以在 if 包装器中隐藏生成这些的复杂性,但这是我能得到的最接近的 :)

    function is(expr, op1, op2) {
        return expr ? op(op1) : op(op2);
    }
    
    function aPlusAbsB(a, b) {
        return (is(b > 0, '+', '-')(a, b));
    }
    

    【讨论】:

      【解决方案4】:

      我认为其他人都是先到这里的,但是 JS 的纯粹功能性比 lisp 稍差,运算符不是函数或对象,而是运算符。

      【讨论】:

        【解决方案5】:

        这取决于您觉得 lisp 实现的哪些方面特别漂亮。我将提出您建议的另一个版本,我认为通过做一些肮脏的事情最终会更接近您的 lisp 定义的语法。

        // Give ourselves + and - functions to level the playing field with lisp.
        Number.prototype['+'] = function(x)this+x;
        Number.prototype['-'] = function(x)this-x;
        
        // Now we can have some fun.
        var aPlusAbsB = function(a,b) a [b > 0 ? '+' : '-'] (b);
        
        // Some other notable language barrier differences, but not too dissimilar?
        // (define (a-plus-abs-b a b) ((if (> b 0) + -) a b))
        

        【讨论】:

          【解决方案6】:

          是的,这不是绝对可能的,你能做的最接近的事情就是在里面嵌套加法和减法函数。

          var aPlusAbsB = function(a, b) {
              return (function(a, b) { b > 0 ? a + b : a - b })(a, b);
          }
          

          不完全一样,但它以一种足够间接的方式完成了工作。

          【讨论】:

            猜你喜欢
            • 2013-01-28
            • 2020-01-23
            • 2011-11-24
            • 1970-01-01
            • 1970-01-01
            • 2013-07-10
            • 2013-03-04
            • 2019-01-27
            • 2011-10-16
            相关资源
            最近更新 更多