2011-11-02 13 views
7

Mientras lee Programming Ruby, me encontré con este fragmento de código:¿Por qué Ruby me deja llamar a un método String sin especificar la cadena?

while gets 
    num1, num2 = split /,/ 
end 

Aunque intuitivamente entiendo lo que hace, no entiendo la sintaxis. 'split' es un método en la clase String, en el lenguaje de Ruby, ¿qué cadena es el receptor del mensaje 'dividir' en el escenario anterior?

Puedo ver en los documentos que 'obtiene' asigna su resultado a la variable $ _, así que supongo que está usando implícitamente $ _ como receptor, pero un montón de búsquedas en Google no han podido confirmar que adivinar. Si ese es el caso, me gustaría saber qué regla general para los métodos invocados sin un receptor explícito.

Probé el código en irb, agregué algunas llamadas de diagnóstico y verifiqué que el comportamiento real es el que esperaría - num1 y num2 obtienen valores asignados que fueron ingresados ​​separados por una coma.

Respuesta

6

Ruby 1.8 tiene un método Kernel#split([pattern [, limit]]) que es idéntico a $_.split(pattern, limit), y gets establece el valor de $_.

4

Básicamente se clavó con su explicación (al menos para 1.8.7, 1.9.3 me dio un NoMethodError para main), pero en mi humilde opinión que es Ruby horrible (o tal vez alguien cambiar de Perl). Si se vuelve a escribir a algo así como esto, se vuelve mucho más claro:

while input = gets.chomp 
    num1, num2 = input.split(/,/) 
end 

La regla general para las llamadas de método sin un receptor es que se envían a self, sea lo que sea en el contexto actual. En el nivel superior es el ya mencionado main, el Período de bucle $_ parece haber desaparecido en 1.9.

+1

'$ _' todavía existe (y lo usa' gets') en Ruby 1.9, pero el método 'Kernel # split' se ha ido. Funcionó previamente no porque se llamara a 'split' en' $ _', sino porque se llamaba a 'Kernel'. –

+0

Sí, lo expresé muy mal. –

+0

@MichelleTilley: se está llamando a 'self', que en ese momento es' main', no 'Kernel'. La clase 'main' es' Object', y 'Object' hereda de' Kernel' (más precisamente * mixes en * 'Kernel'), pero eso de ninguna manera significa que el método está siendo llamado en' Kernel'. (Usted * podría * teóricamente llamarlo en 'Kernel', porque la clase' Kernel' es 'Module',' Module' hereda de 'Object', que mezcla en' Kernel' y así 'Kernel' es una instancia de sí mismo , pero esa es una manera terriblemente confusa de decirlo). –

Cuestiones relacionadas