2011-11-02 8 views
7

Podczas czytania Programming Ruby, natknąłem tym fragmencie kodu:Dlaczego Ruby pozwala mi wywołać metodę String bez określania ciągu znaków?

while gets 
    num1, num2 = split /,/ 
end 

Choć intuicyjnie zrozumieć, co robi, nie rozumiem składni. "split" to metoda na klasie String - w języku Ruby, który łańcuch jest odbiorcą komunikatu "split" w powyższym scenariuszu?

Widzę w dokumentach, że "dostaje" przypisuje swój wynik do zmiennej $ _, więc domyślam się, że domyślnie używa ona $ _ jako odbiornika - ale cała masa wyszukiwania Google nie potwierdziła tego odgadnąć. Jeśli tak jest, chciałbym wiedzieć, jaka jest ogólna reguła dla metod wywoływanych bez jawnego odbiornika.

Próbowałem kodu w irb, dodałem kilka wywołań diagnostycznych i zweryfikowałem, że rzeczywiste zachowanie jest takie, jakiego można się spodziewać - num1 i num2 otrzymują przypisane wartości, które zostały wprowadzone oddzielone przecinkiem.

Odpowiedz

6

Ruby 1.8 ma metodę Kernel#split([pattern [, limit]]) identycznego $_.split(pattern, limit) i gets ustawia wartość $_.

4

Zasadniczo przybity go z wyjaśnieniem (przynajmniej dla 1.8.7, 1.9.3 dał mi NoMethodError dla main), ale IMHO to straszne Ruby (a może ktoś przełączania z Perl). Jeśli przepisać go do czegoś takiego, to staje się o wiele wyraźniej:

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

Zasada ogólna dla metody połączenia bez odbiornika jest to, że są one wysyłane do self, cokolwiek to może być w obecnej sytuacji. Na wyższym poziomie jest wyżej wymieniony main, perlism w pętli $_ wydaje się zniknąć w 1.9.

+1

'$ _' nadal istnieje (i jest używane przez' gets') w Rubim 1.9, ale metoda 'Kernel # split' zniknęła. Pracował wcześniej nie dlatego, że 'split' był wywoływany na' $ _', ale dlatego, że był wywoływany w 'Kernel'. –

+0

Tak, sformułowałem to bardzo źle. –

+0

@MichelleTilley: jest wywoływany na 'self', który w tym miejscu jest' main', a nie 'Kernel'. 'główna klasa to' Object', a 'Object' dziedziczy z' Kernel' (dokładniej * miesza się w * 'Kernel'), ale to w żadnym wypadku nie oznacza, że ​​metoda jest wywoływana w' Kernel'. (Ty * możesz * teoretycznie nazwać to na 'Kernel', ponieważ' klasa jądra 'to' Module', 'Module' dziedziczy po' Object', która miesza się w 'Kernel', a tym samym' Kernel' jest instancją samego siebie , ale jest to bardzo mylący sposób na wyrażenie tego.) –

Powiązane problemy