获取对运算符后面的JavaScript Function对象的引用

时间:2010-03-09 23:35:43

标签: javascript functional-programming lisp scheme

这是一个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语言中的核心函数,就好像它们是用户定义的一样?

6 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分: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))

答案 2 :(得分: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));
}

答案 3 :(得分:1)

我认为其他人都先来到这里,但是JS的功能略逊于lisp,运算符不是函数或对象,而是运算符。

答案 4 :(得分:0)

这比你的建议略微漂亮,虽然远不及你的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))))))

答案 5 :(得分:0)

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

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

不完全相同,但它以足够间接的方式完成工作。