Iterator .inject

Witam.

Zastanawiam się dlaczego nie mogę wyświetlić wartości bloku przy każdej iteracji.

code.inject do |mem, element|
print “#{mem *= element}”
end[/code]
Jeżeli usunę printa, to program działa bez problemu.

Cóż masz za error? Czego zwróconego z bloku oczekuje inject a co zwraca wywołanie ‘print’? Pytania powinny Cię nakierować.

Zależało mi na tym, aby “podejrzeć” jak krok po kroku blok liczy wartości silni.
Końcową wartość obliczeń wiem jak wywołać.

hubertlepicki miał na myśli to byś pomyślał co zwraca metoda print i czemu masz błąd undefined metod for nil (bo zakłądam, że właśnie taki to błąd). Do kolejnej iteracji w inject jako ‘mem’ wpadnie Ci to co zwraca ostatni instrukcja w bloku, w tym przypadku to co zwraca print.

Pewnie chodziło Ci o coś takiego:

code=‘ruby’.inject do |mem, element|
print "#{mem *= element} "
mem
end[/code]
Pierwszy wiersz wewnątrz bloku wyświetla co chciałeś zobaczyć, drugi, tak jak napisał seban zwraca do inject to co powinien jeśli ma wyliczyć silnię.

code=ruby.inject do |mem, element|
p(mem *= element)
end[/code]
p wyrzuca na konsolę (wołając metodę inspect, a nie to_s) i zwraca wartość przekazaną do tej metody. Najlepsza opcja w tym wypadku.

code.inject do |mem, element|
p(mem *= element)
end[/code]
To mi działa. Natomiast metoda zaproponowana przez meek już nie (Ruby 1.9.3). Dzięki za podpowiedzi.

Obie metody działają, tylko ta z print wyświetla wszystkie kolejne numery i potem wynik w jednej linii, u mnie pod 1.9.3-p194 działa bez problemu

Właśnie zabierałem się za pisanie nowego topicu o metodzie inject i obliczaniu silni, a tu widzę że nie tylko ja mam problem z tym zagadnieniem. Rozumiem, że w moim kodzie

puts (1..10).inject{|memory, next_number| memory *= next_number}

wyrażenie

memory *= next_number

zwraca do metody kolejne, pomnożone przez siebie wartości. Zatem dlaczego tego wyrażenia brakuje w tym kodzie

puts (1..10).inject{|memory, next_number| puts memory *= next_number; memory}

No bo jak się domyślam, samo “puts” jedynie wyświetla wynik mnożenia a nie przekazuje go dalej do metody. A po co jest na końcu samotne wyrażenie “memory?” Czy ono jest może domyślnym wynikiem wcześniejszego mnożenia, tego ukrytego w poleceniu “puts”

puts memory *= next_number

i po odpowiednim zwiększeniu swojej wartości jest przekazywane do metody?
I dlaczego w trakcie wykonywania powyższego kodu silni, jest dwukrotnie wyświetlana ostatnia wartość?

Odpal sobie taki kod x = puts "a" i zobaczysz, że x ma wartość nil, to znaczy, że puts jedynie wyświetla jakąś wartość, ale jej nie zwraca. W inject do następnej iteracji jako memory przekazujesz to, co zwróciła poprzednia iteracja. memory *= next_number zwraca wynik mnożenia, ale puts memory *= next_number zwraca nil.

Dlatego, że masz puts w bloku (więc wyświetla wynik każdej iteracji) i masz puts na początku linii kodu, wiec wyświetla też wynik działania całej funkcji inject

Skoro puts memory *= next_number zwraca wyrażenie nil, to co w kodzie

puts (1..10).inject{|memory, next_number| puts memory *= next_number; memory}

zwraca wynik mnożenia dwóch kolejnych liczb? Przecież samo memory nie jest powiekszane o kolejne mnożenia.

memory jest jak najbardziej powiększane, taka rola tej zmiennej. Może poniższa forma będzie bardziej zrozumiała.

(1..10).inject{|memory, next_number| puts(memory = memory*next_number); memory}

Najpierw wykonywane jest wyrażenie w nawiasie, czyli przypisanie do memory iloczynu jej samej i next_number. Dopiero później puts wyświetla wynik takiego przypisania.

Ale skąd zmienna memory, ta na końcu kodu “wie” że została powiększona? Przecież puts(memory = memory*next_number) po wyświetleniu wyniku zwróci jedynie nil, a więc nie przekaże informacji do memory że jest już powiększona.

Metoda puts nie ma za zadanie przekazania czegokolwiek. Jest użyta kontrolnie, aby listować jak się zmienia memory. Może jeszcze inaczej:

(1..10).inject{|memory, next_number| memory *= next_number; puts memory; memory}

i coś takiego:

2.1.2 :022 > x = 5 => 5 2.1.2 :023 > puts x *= 4 20 => nil 2.1.2 :024 > x => 20 2.1.2 :025 >