Вот процедура шепелявости, которая просто добавляет к абсолютному значению '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);
}
Основная проблема состоит в том, что я не могу использовать +
и -
символы как ссылки на функции, которые они действительно представляют, как я могу с шепелявостью. Кто-либо может придумать более корректный способ сделать что-то вроде этого, или я поразил границу языка?
Очевидно, я могу сделать это:
var aPlusAbsB = function(a,b) {
return a + Math.abs(b);
}
, но это - больше мысленного эксперимента, чем прагматический вопрос.
Есть ли какой-либо способ, которым я могу получить ссылку на базовые функции на языке сценариев JavaScript так же, как если бы они были пользовательскими?
Это очень крутая идея - она отлично подходит для оценки математических выражений, но вы просто не можете установить оператор (или логику, стоящую за ним) для переменной. Извините: -)
Это зависит от того, какие аспекты реализации 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))
Я думаю, что все остальные попали сюда первыми, но JS немного менее функционально, чем 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))))))
Хотя это не так элегантно, как код 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));
}
Да, это не совсем возможно, самое близкое, что вы можете сделать, - это вложить внутрь функции сложения и вычитания.
var aPlusAbsB = function(a, b) {
return (function(a, b) { b > 0 ? a + b : a - b })(a, b);
}
Не совсем то же самое, но он выполняет свою работу достаточно косвенным образом.