2010-03-09 7 views
7

Aquí es un procedimiento Lisp que simplemente añade 'a' al valor absoluto de la 'b':Conseguir referencia al objeto de función JavaScript detrás de un operador

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

creo que esto es hermoso, y yo estoy tratando para encontrar la mejor manera de escribir esto en JavaScript. Pero mi código JavaScript no es bello:

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); 
} 

El principal problema es que no puedo utilizar los + y - símbolos como referencias a las funciones que realmente representan como pueda con Lisp. ¿Alguien puede pensar en una forma más elegante de hacer algo como esto, o he alcanzado un límite de idioma?

Obviamente, no puedo hacer esto:

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

, pero esto es más bien un experimento mental que una cuestión pragmática.

¿Hay alguna manera de que pueda obtener una referencia a las funciones básicas en el lenguaje JavaScript como si estuvieran definidas por el usuario?

+0

¿Has mirado Functional.js y su sintaxis extravagante para representar funciones simples como cadenas? – Pointy

+0

Tampoco tengo idea de si realmente hay instancias de Function en algún sentido real para los operadores aritméticos incorporados. – Pointy

+0

He visto la biblioteca funcional y parece genial. Me pregunto si hay alguna forma de hacer esto usando solo JS básico. Y @Pointy me preguntaba lo mismo. Puede que no sean objetos Function, pero existe una lógica que se ejecuta de forma similar a cómo se ejecuta una función. –

Respuesta

5

Es una idea genial, sería genial para evaluar expresiones matemáticas, pero simplemente no se puede establecer un operador (o la lógica detrás de él) a una variable. Lo sentimos :-)

+0

Odio darte un +1 por el bien del OP, pero es verdad, hay poco que puedes hacer al respecto. –

+0

@musicfreak: lol gracias ;-) A menudo pensé en esto porque ha habido ocasiones en que he tenido que verificar el estado de una variable para decidir si '' 'o' -', pero hubiera sido demasiado más fresco si hubiera pasado el '+' o el '-' en su lugar, ¡habría guardado toda una declaración' si'! –

+0

A menos que se demuestre lo contrario por parte de un experto itinerante de JavaScript, esta parece ser la respuesta :(. –

0

Esta cifra es ligeramente más bella que su sugerencia, aunque lejos de ser tan hermosa como su representación Lisp del concepto:

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); 
} 

Esto sería equivalente a la siguiente en el esquema:

(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

Aunque no es tan elegante como el código LISP, puede crear una función dinámicamente que actúa como un operador (en números), pero no lo es.

function op(o) { 
    return new Function("a", "b", "return a " + o + " b"); 
} 


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

Además, podemos ocultar la complejidad de la generación de estos dentro de un if envoltorio, pero eso es lo más cerca que puedo conseguir :)

function is(expr, op1, op2) { 
    return expr ? op(op1) : op(op2); 
} 

function aPlusAbsB(a, b) { 
    return (is(b > 0, '+', '-')(a, b)); 
} 
1

Creo que todos los demás dieron aquí en primer lugar, pero JS es un poco menos funcional que el ceceo, los operadores no son funciones u objetos, sino operadores.

5

Depende de qué aspectos de la implementación de lisp encuentre especialmente bellos. Propondré otra versión de tu sugerencia que creo que termina un poco más cerca de la sintaxis de la definición de lisp al hacer algunas cosas sucias.

// 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)) 
0

Sí, eso no es estrictamente posible, lo más cercano que puede hacer es agregar y restar funciones en el interior.

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

No es exactamente lo mismo, pero hace el trabajo de forma suficientemente indirecta.

Cuestiones relacionadas