-
Jakiego typu jest puts? Instrukcja puts puts.class wypisuje mi NilClass, a to przecież klasa reprezentujaca nil.
-
Nawet jeśli puts to NilClass, któremu przypisano dynamicznie nowe metody to jak mogę znaleźć informacje o puts w dokumentacji? Nie wiem od czego zacząć tu szukać, bo przecież nazwa klasy nic mi nie powie.
-
Jak wywołać obiekt? W przypadku puts nie podaje nazwy metody, tylko od razu podaje za nim argumenty, czy może mi ktoś powiedzieć na czym polega ta sztuczka? Najlepiej na przykładzie własnej klasy, która będzie wywoływać jakąś metodę bez podawania jej nazwy.
- Jest to metoda, zwraca nil
- http://ruby-doc.org/core/classes/Kernel.html#M001403 co dalej doprowadzi Cię do http://www.ruby-doc.org/core/classes/IO.html#M000893
- puts jest zdefiniowany w module Kernel, który jest dołączony do wszystkich obiektów. “puts” to nazwa metody, nie obiektu.
Jeśli nie wiesz czy dane coś jest metodą czy zmienną, zawsze możesz sprawdzić przy pomocy operatora “defined?”, na przykład:
ruby-1.9.2-p180-patched :011 > defined? $stdout
=> "global-variable"
ruby-1.9.2-p180-patched :012 > defined? puts
=> "method"
AD 3. Samo puts jest definiowane na poziomie parsera, to funkcja globalna.
W zasadzie samo “puts” tylko udaje metode. Jest to wywołanie funkcji która sprawdza czy była wywołana z receiverem i jeśli nie ustawia go na $stdout, $stdout akurat ma taką metodę więc wszystko śmiga.
[quote=Paweł Kondzior]AD 3. Samo puts jest definiowane na poziomie parsera, to funkcja globalna.
W zasadzie samo “puts” tylko udaje metode. Jest to wywołanie funkcji która sprawdza czy była wywołana z receiverem i jeśli nie ustawia go na $stdout, $stdout akurat ma taką metodę więc wszystko śmiga.[/quote]
Serio? A nie w module Kernel, jak napisałem kilka linijek wyżej?
[quote=Paweł Kondzior]AD 3. Samo puts jest definiowane na poziomie parsera, to funkcja globalna.
W zasadzie samo “puts” tylko udaje metode. Jest to wywołanie funkcji która sprawdza czy była wywołana z receiverem i jeśli nie ustawia go na $stdout, $stdout akurat ma taką metodę więc wszystko śmiga.[/quote]
E tam.
https://github.com/ruby/ruby/blob/ruby_1_9_2/io.c#L6175 → https://github.com/ruby/ruby/blob/ruby_1_9_2/io.c#L9907 → https://github.com/ruby/ruby/blob/ruby_1_9_2/class.c#L1333 – puts jest normalną metodą modułu Kernel.
To tylko wygenerowana dokumentacja.
ruby-1.9.2-head :001 > include Kernel
=> Object
ruby-1.9.2-head :002 > self.methods.grep /puts/
=> []
Coś niebardzo.
Inaczej, samo puts ma sie zachowywac jak metoda. Odwołać się to tego co pokazałeś powyżej. Ale patrzcie na to:
self.method(:puts).call("123") <- ok
self.send(:puts, "123") <- ok
self.puts <- niema metody
Ależ jak najbardziej. Oraz:
Kernel.methods.include? :puts # => true
[quote=Paweł Kondzior]Ale patrzcie na to:
self.method(:puts).call("123") <- ok
self.send(:puts, "123") <- ok
self.puts <- nie ma metody
[/quote]
Oczywiście, że jest, tylko jest metodą prywatną, więc nie wolno jej wołać z jawnym receiverem.
To tylko wygenerowana dokumentacja.
ruby-1.9.2-head :001 > include Kernel
=> Object
ruby-1.9.2-head :002 > self.methods.grep /puts/
=> []
Coś niebardzo.
Inaczej, samo puts ma sie zachowywac jak metoda. Odwołać się to tego co pokazałeś powyżej. Ale patrzcie na to:
self.method(:puts).call("123") <- ok
self.send(:puts, "123") <- ok
self.puts <- niema metody
[/quote]
Nadal mnie nie przekonałeś bo:
ruby-1.9.2-p180-patched :001 > self.puts "ziom"
NoMethodError: private method `puts' called for main:Object
więc wygląda że jest po prostu metodą prywatną (i nie możesz jej wywołać podając odbiorcę - self).
Ponad to:
ruby-1.9.2-p180-patched :008 > self.private_methods.include? :puts
=> true
Więc puts nie jest niczym specjalnym tym bardziej na poziomie parsera.
Trochę odbiegliście od tematu bo ja próbowałem wyjaśnić jak to się dzieje w Ruby że puts zawsze wie do jakiego obiektu należy, i że nie jest to wcale self
No ale jest to self, każdy obiekt każdej klasy ma dołączoną metodę puts z modułu Kernel. Sorry, ale nieprecyzyjne formułowanie tego typu opinii może wprowadzać kogoś w błąd, szczególnie jeśli jest początkujący i myśli sobie że tu jest jakaś “magia”. Magii nie ma.
No wygląda na to że jednak gadałem głupoty.
Ależ oczywiście, że jest.
class Foo; end
Foo.new.private_methods.include? :puts # => true
No ale jest to self, każdy obiekt każdej klasy ma dołączoną metodę puts z modułu Kernel. Sorry, ale nieprecyzyjne formułowanie tego typu opinii może wprowadzać kogoś w błąd, szczególnie jeśli jest początkujący i myśli sobie że tu jest jakaś “magia”. Magii nie ma.[/quote]
Spoko, nie wiem czemu wszędzie widziałem tam undefined method, a to było private method. Zadługa impreza była w piątek. Wszystko powyższe co napisałem to totalne głupoty.
Spoko, zmusiłeś niektórych do zajrzenia w dokumentację, innych w kod, więc moim zdaniem pozytyw ;).
Paweł, może Ci się pomyliło z pythonowym print, które do wersji < 3.0 było właśnie elementem składni a nie żadną funkcją?
Dzięki hubertlepicki. Chyba lewą nogą dziś wstałem skoro o puts pomyślałem jak o obiekcie.
Nie, widziałem wszędzie undefined więc sobie jakoś to wytłumaczyłem, w ostateczności to czysty PEBCAK. Jak już powiedzialem impreza w piątek była zadługa