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.
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 >