2009-11-06 16 views
19

Revisé la última versión de Ruby, para jugar un poco con los últimos cambios. Lo primero que intenté hacer fue llamar a un Ruby lambda/block/proc como lo haría con un Python invocable.¿Por qué no es posible la llamada lambda 1.9 de Ruby sin el punto al frente de los paréntesis?

a = lambda {|x| puts x} 
a.call(4) # works, and prints 4 
a[4] # works and prints 4 
a.(4) # same 
a(4) # undefined method 'a' for main:Object 

¿Por qué la última llamada no es posible? ¿Alguna vez será?

Respuesta

10

AFAIK es porque ruby ​​no le permite definir el método () para un objeto. La razón por la que no le permite definir el método () es probablemente debido al hecho de que los paréntesis son opcionales en las llamadas a métodos.

Y por si sirve de algo, aquí hay un truco para permitir que se invoca usando lambdas ()http://github.com/coderrr/parenthesis_hacks/blob/master/lib/lambda.rb

+0

¿Puedes explicar un poco el script lambda? – Geo

+0

bien, cuando intenta invocar un método llamado 'blah()' y 'method_missing' se activa, comprueba si una lambda llamada' blah' está definida en el contexto apropiado. Si se define una lambda así, simplemente invoca lambda utilizando la sintaxis habitual de 'blah.call', también pasa junto con los parámetros que se dieron – horseyguy

+0

. Creo que es un hack impresionante. Gracias. – Geo

6

Ruby es básicamente 100% orientado a objetos, pero a veces intenta ocultar este hecho por ... ¿conveniencia? ¿Familiaridad?

Básicamente, las funciones definidas "en el nivel superior" se definen realmente como métodos en un objeto global. Para que funcione, una llamada sin un especificador se convierte realmente a llamar a un método con ese nombre en dicho objeto global. Este estilo hace que las cosas parezcan más script-y. Ruby está tratando de hacer eso con tu último ejemplo.

Los primeros dos ejemplos se analizan bien porque Ruby sabe que está intentando acceder a los métodos del objeto proc: recuerde que incluso [] es solo un método que puede definir. El que tiene el punto explícito también funciona porque el punto significa "enviar este mensaje a este objeto" (en este caso, a).

Sé que no "resuelve" nada, pero espero que ayude un poco.

+1

El hecho de que el rubí es programación orientada a objetos no explica por qué no se puede usar '()' para invocar una lambda. Muchos idiomas le permiten definir un método '()' para sus objetos. La pregunta es por qué doesn ruby ​​le permite definir un operador '()'? – horseyguy

+1

(Justo ahora vi este comentario ...) Buena pregunta. Tal vez tiene algo que ver con la forma en que puede omitir paréntesis en ciertas situaciones; Sería extraño tener una llamada de operador sobrecargada implícita. –

Cuestiones relacionadas