W języku Ruby metody mogą odbierać blok kodu w celu wykonania dowolnych segmentów kodu.
Gdy metoda oczekuje bloku, wywołuje go, wywołując yieldfunkcję.
Jest to bardzo przydatne, na przykład, do iteracji po liście lub zapewnienia niestandardowego algorytmu.
Weź następujący przykład:
Mam zamiar zdefiniować Personklasę zainicjowaną nazwą i podać do_with_namemetodę, która po wywołaniu przekaże nameatrybut do otrzymanego bloku.
classPersondef initialize( name )@name= name
enddef do_with_name
yield(@name)endend
Pozwoliłoby nam to wywołać tę metodę i przekazać dowolny blok kodu.
Na przykład, aby wydrukować nazwę, zrobilibyśmy:
person =Person.new("Oscar")#invoking the method passing a block
person.do_with_name do|name|
puts "Hey, his name is #{name}"end
Wydrukowałby:
Hey, his name is Oscar
Zauważ, że blok otrzymuje jako parametr zmienną o nazwie name(uwaga: możesz wywoływać tę zmienną w dowolny sposób, ale warto ją wywołać name). Po wywołaniu kodu yieldwypełnia ten parametr wartością @name.
yield(@name)
Możemy zapewnić kolejny blok, aby wykonać inną akcję. Na przykład odwróć nazwę:
#variable to hold the name reversed
reversed_name =""#invoke the method passing a different block
person.do_with_name do|name|
reversed_name = name.reverse
end
puts reversed_name
=>"racsO"
Zastosowaliśmy dokładnie tę samą metodę ( do_with_name) - to tylko inny blok.
Ten przykład jest trywialny. Bardziej interesujące zastosowania to filtrowanie wszystkich elementów w tablicy:
days =["monday","tuesday","wednesday","thursday","friday"]# select those which start with 't'
days.select do| item |
item.match /^t/end=>["tuesday","thursday"]
Lub możemy również dostarczyć niestandardowy algorytm sortowania, na przykład na podstawie rozmiaru ciągu:
Niestety, nazwa jest zmienną instancji zainicjowaną za pomocą "Oscar" (nie jest bardzo jasne w odpowiedzi)
OscarRyz
Co z takim kodem? person.do_with_name {|string| yield string, something_else }
f .ardelian
7
Tak więc, w kategoriach Javascripty, jest to znormalizowany sposób przekazywania wywołania zwrotnego do danej metody i wywoływania jej. Dziękuję za wyjaśnienie!
yitznewton,
Mówiąc bardziej ogólnie - blok to rubinowy „ulepszony” cukier składniowy dla wzorca strategii. ponieważ typowym zastosowaniem jest dostarczenie kodu do zrobienia czegoś w kontekście innej operacji. Ale ulepszenia ruby otwierają drogę do tak fajnych rzeczy, jak pisanie DSL-ów za pomocą bloku do przekazywania kontekstu
Roman Bułhakow
25
W języku Ruby metody mogą sprawdzić, czy zostały wywołane w taki sposób, że oprócz zwykłych argumentów podano blok. Zwykle odbywa się to za pomocą block_given?metody, ale można również odwołać się do bloku jako jawnego Proc, poprzedzając znak ampersand ( &) przed ostateczną nazwą argumentu.
Jeśli metoda jest wywoływana z blokiem, metoda może yieldsterować blokiem (wywołać blok) z pewnymi argumentami, jeśli to konieczne. Rozważ tę przykładową metodę, która pokazuje:
def foo(x)
puts "OK: called as foo(#{x.inspect})"yield("A gift from foo!")if block_given?end
foo(10)# OK: called as foo(10)
foo(123){|y| puts "BLOCK: #{y} How nice =)"}# OK: called as foo(123)# BLOCK: A gift from foo! How nice =)
Lub używając specjalnej składni argumentu blokowego:
def bar(x,&block)
puts "OK: called as bar(#{x.inspect})"
block.call("A gift from bar!")if block
end
bar(10)# OK: called as bar(10)
bar(123){|y| puts "BLOCK: #{y} How nice =)"}# OK: called as bar(123)# BLOCK: A gift from bar! How nice =)
Całkiem możliwe, że ktoś udzieli tu naprawdę szczegółowej odpowiedzi, ale zawsze uważałem ten post Roberta Sosińskiego za doskonałe wyjaśnienie subtelności między blokami, procami i lambdami.
Powinienem dodać, że moim zdaniem post, do którego prowadzę link, jest specyficzny dla ruby 1.8. Niektóre rzeczy uległy zmianie w Ruby 1.9, na przykład zmienne blokowe są lokalne dla bloku. W wersji 1.8 otrzymasz coś takiego:
>> a ="Hello"=>"Hello">>1.times{|a| a ="Goodbye"}=>1>> a
=>"Goodbye"
Podczas gdy 1.9 zapewni Ci:
>> a ="Hello"=>"Hello">>1.times{|a| a ="Goodbye"}=>1>> a
=>"Hello"
Nie mam 1.9 na tym komputerze, więc powyższe może zawierać błąd.
@klenwell dzięki za zgłoszenie, zaktualizowałem link ponownie.
theIV
13
Chciałem w pewnym sensie dodać, dlaczego tak robisz w odpowiedzi na i tak świetne odpowiedzi.
Nie mam pojęcia, z jakiego języka pochodzisz, ale zakładając, że jest to język statyczny, tego rodzaju rzeczy będą wyglądały znajomo. W ten sposób czytasz plik w Javie
publicclassFileInput{publicstaticvoid main(String[] args){File file =newFile("C:\\MyFile.txt");FileInputStream fis =null;BufferedInputStream bis =null;DataInputStream dis =null;try{
fis =newFileInputStream(file);// Here BufferedInputStream is added for fast reading.
bis =newBufferedInputStream(fis);
dis =newDataInputStream(bis);// dis.available() returns 0 if the file does not have more lines.while(dis.available()!=0){// this statement reads the line from the file and print it to// the console.System.out.println(dis.readLine());}// dispose all the resources after using them.
fis.close();
bis.close();
dis.close();}catch(FileNotFoundException e){
e.printStackTrace();}catch(IOException e){
e.printStackTrace();}}}
Ignorując cały łańcuch związany z strumieniem, Chodzi o to
Tutaj, zamiast zajmować się krokiem pierwszym i drugim, w zasadzie delegujesz to do innej klasy. Jak widać, radykalnie zmniejsza to ilość kodu, który musisz napisać, co ułatwia czytanie i zmniejsza ryzyko wycieków pamięci lub braku możliwości usunięcia blokad plików.
Teraz nie jest tak, że nie można zrobić czegoś podobnego w java, w rzeczywistości ludzie robią to od dziesięcioleci. To się nazywa wzór strategii . Różnica polega na tym, że bez bloków, w przypadku czegoś tak prostego jak przykład pliku, strategia staje się nadmierna z powodu ilości klas i metod, które musisz napisać. W przypadku bloków jest to tak prosty i elegancki sposób, aby to zrobić, że NIE ma sensu NIE strukturyzować kodu w ten sposób.
Nie jest to jedyny sposób, w jaki używane są bloki, ale inne (jak wzorzec Konstruktora, który można zobaczyć w form_for api w szynach) są na tyle podobne, że powinno być oczywiste, co się dzieje, gdy obejdziesz się tym. Kiedy widzisz bloki, zwykle bezpiecznie jest założyć, że wywołanie metody jest tym, co chcesz zrobić, a blok opisuje, jak chcesz to zrobić.
Uprośćmy to trochę: File.readlines("readfile.rb").each_with_index do |line, index| puts "#{index + 1}: #{line}" endi śmiejmy się jeszcze mocniej z ludzi z Java.
Michael Hampton
1
@MichaelHampton, śmiej się po przeczytaniu pliku o długości kilku gigabajtów.
akostadinov
@akostadinov Nie ... to sprawia, że chcę płakać!
Michael Hampton
3
@MichaelHampton Lub, jeszcze lepiej: IO.foreach('readfile.rb').each_with_index { |line, index| puts "#{index}: #{line}" }(plus brak problemów z pamięcią)
pozew Fund Moniki
12
Uważam, że ten artykuł jest bardzo przydatny. W szczególności następujący przykład:
#!/usr/bin/rubydef test
yield5
puts "You are in the method test"yield100end
test {|i| puts "You are in the block #{i}"}
test do|i|
puts "You are in the block #{i}"end
co powinno dać następujące dane wyjściowe:
You are in the block 5You are in the method test
You are in the block 100You are in the block 5You are in the method test
You are in the block 100
Zasadniczo za każdym razem, gdy zostanie wykonane wywołanie yieldruby, uruchomi kod w dobloku lub w środku {}. Jeśli podano parametr, yieldto zostanie on podany jako parametr do dobloku.
Dla mnie to był pierwszy raz, kiedy naprawdę zrozumiałem, co dorobią bloki. Zasadniczo jest to sposób, w jaki funkcja umożliwia dostęp do wewnętrznych struktur danych, zarówno w celu iteracji, jak i konfiguracji funkcji.
Uruchomi to respond_tofunkcję, która zwróci doblok z parametrem (wewnętrznym) format. Następnie wywołujesz .htmlfunkcję dla tej zmiennej wewnętrznej, co z kolei daje blok kodu do uruchomienia renderpolecenia. Pamiętaj, że .htmlprzyniesie to tylko wtedy, gdy jest to wymagany format pliku. (technicznie: te funkcje faktycznie block.callnie używają tego, yieldco widać ze źródła, ale funkcjonalność jest zasadniczo taka sama, zobacz to pytanie w celu omówienia.) Zapewnia to sposób, aby funkcja wykonała pewną inicjalizację, a następnie pobierała dane wejściowe z kodu wywołującego i następnie w razie potrzeby kontynuować przetwarzanie.
Innymi słowy, jest podobny do funkcji przyjmującej anonimową funkcję jako argument, a następnie wywołującej ją w javascript.
W Ruby blok jest zasadniczo fragmentem kodu, który można przekazać i wykonać dowolną metodą. Bloki są zawsze używane z metodami, które zwykle przekazują im dane (jako argumenty).
Bloki są szeroko stosowane w klejnotach Ruby (w tym Railsach) oraz w dobrze napisanym kodzie Ruby. Nie są obiektami, dlatego nie można ich przypisywać do zmiennych.
Podstawowa składnia
Blok to fragment kodu ujęty w {} lub do..end. Zgodnie z konwencją w przypadku bloków jednowierszowych należy stosować składnię nawiasów klamrowych, aw przypadku bloków wieloliniowych należy stosować składnię do..end.
{# This is a single line block }do# This is a multi-line blockend
Każda metoda może otrzymać blok jako domyślny argument. Blok jest wykonywany przez instrukcję return w ramach metody. Podstawowa składnia to:
def meditate
print "Today we will practice zazen"yield# This indicates the method is expecting a blockend# We are passing a block as an argument to the meditate method
meditate { print " for 40 minutes."}Output:Today we will practice zazen for40 minutes.
Po osiągnięciu instrukcji fedrowania metoda medytacji daje kontrolę nad blokiem, kod w bloku jest wykonywany, a kontrola jest zwracana do metody, która wznawia wykonywanie natychmiast po instrukcji fed.
Gdy metoda zawiera instrukcję dochodu, oczekuje otrzymania bloku w czasie wywołania. Jeśli blok nie zostanie podany, wyjątek zostanie zgłoszony po osiągnięciu instrukcji dochodu. Możemy uczynić blok opcjonalnym i uniknąć generowania wyjątku:
def meditate
puts "Today we will practice zazen."yieldif block_given?end meditate
Output:Today we will practice zazen.
Nie można przekazać wielu bloków do metody. Każda metoda może otrzymać tylko jeden blok.
Dobrze ale dlaczego ? Istnieje wiele powodów, takich jak to, Loggerże użytkownik nie musi wykonywać jakiegoś zadania, jeśli użytkownik nie musi tego robić. Powinieneś jednak wyjaśnić swoje ...
Ulysse BN
4
Mówiąc prościej, Yields pozwala, aby tworzona metoda przyjmowała i wywoływała bloki. Słowo kluczowe wydajności w szczególności jest miejscem, w którym zostaną wykonane „rzeczy” w bloku.
Chciałbym tu wspomnieć o dwóch kwestiach dotyczących wydajności. Po pierwsze, podczas gdy wiele odpowiedzi tutaj mówi o różnych sposobach przekazania bloku do metody wykorzystującej wydajność, porozmawiajmy również o przepływie sterowania. Jest to szczególnie istotne, ponieważ możesz dać WIELU CZASÓW blokowi. Spójrzmy na przykład:
classFruit
attr_accessor :kinds
def initialize
@kinds=%w(orange apple pear banana)enddef each
puts 'inside each'3.times{yield(@kinds.tap {|kinds| puts "selecting from #{kinds}"}).sample }endend
f =Fruit.new
f.each do|kind|
puts 'inside block'end=> inside each
=> selecting from ["orange","apple","pear","banana"]=> inside block
=> selecting from ["orange","apple","pear","banana"]=> inside block
=> selecting from ["orange","apple","pear","banana"]=> inside block
Po wywołaniu każdej metody wykonuje się linia po linii. Teraz, gdy przejdziemy do bloku 3. razy, ten blok zostanie wywołany 3 razy. Za każdym razem, gdy wywołuje plon. Ta wydajność jest powiązana z blokiem związanym z metodą, która wywołała każdą metodę. Należy zauważyć, że za każdym razem, gdy wywoływana jest wydajność, zwraca kontrolę z powrotem do bloku każdej metody w kodzie klienta. Po zakończeniu wykonywania blok wraca do bloku 3. razy. I dzieje się to 3 razy. Tak więc blok w kodzie klienta jest wywoływany 3 odrębnymi okazjami, ponieważ fedrunek jest jawnie nazywany 3 oddzielnymi czasami.
Moja druga uwaga dotyczy enum_for i fed. enum_for tworzy instancję klasy Enumerator, a ten obiekt Enumerator odpowiada również na fed.
Zauważ więc, że za każdym razem, gdy wywołujemy rodzaje za pomocą zewnętrznego iteratora, wywoła to wydajność tylko raz. Następnym razem, gdy go nazwiemy, wywoła następną wydajność i tak dalej.
Jest ciekawa ciekawostka w odniesieniu do enum_for. Dokumentacja online zawiera następujące informacje:
enum_for(method =:each,*args)→ enum
Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.
str ="xyz"
enum = str.enum_for(:each_byte)
enum.each {|b| puts b }# => 120# => 121# => 122
Jeśli nie podasz symbolu jako argumentu dla enum_for, ruby podłączy moduł wyliczający do każdej metody odbiornika. Niektóre klasy nie mają każdej metody, na przykład klasa String.
str ="I like fruit"
enum = str.to_enum
enum.next=>NoMethodError: undefined method `each' for "I like fruit":String
Tak więc, w przypadku niektórych obiektów wywoływanych za pomocą enum_for, musisz wyraźnie określić, jaka będzie twoja metoda wyliczania.
Wydajność może być użyta jako blok bezimienny do zwrócenia wartości w metodzie. Rozważ następujący kod:
DefUp(anarg)yield(anarg)end
Możesz utworzyć metodę „W górę”, która ma przypisany jeden argument. Możesz teraz przypisać ten argument, aby uzyskać wynik, który wywoła i wykona powiązany blok. Możesz przypisać blok po liście parametrów.
Up("Here is a string"){|x| x.reverse!; puts(x)}
Gdy wywołanie metody Up daje argument z argumentem, jest on przekazywany do zmiennej blokowej w celu przetworzenia żądania.
Odpowiedzi:
Tak, na początku jest to trochę zagadkowe.
W języku Ruby metody mogą odbierać blok kodu w celu wykonania dowolnych segmentów kodu.
Gdy metoda oczekuje bloku, wywołuje go, wywołując
yield
funkcję.Jest to bardzo przydatne, na przykład, do iteracji po liście lub zapewnienia niestandardowego algorytmu.
Weź następujący przykład:
Mam zamiar zdefiniować
Person
klasę zainicjowaną nazwą i podaćdo_with_name
metodę, która po wywołaniu przekażename
atrybut do otrzymanego bloku.Pozwoliłoby nam to wywołać tę metodę i przekazać dowolny blok kodu.
Na przykład, aby wydrukować nazwę, zrobilibyśmy:
Wydrukowałby:
Zauważ, że blok otrzymuje jako parametr zmienną o nazwie
name
(uwaga: możesz wywoływać tę zmienną w dowolny sposób, ale warto ją wywołaćname
). Po wywołaniu koduyield
wypełnia ten parametr wartością@name
.Możemy zapewnić kolejny blok, aby wykonać inną akcję. Na przykład odwróć nazwę:
Zastosowaliśmy dokładnie tę samą metodę (
do_with_name
) - to tylko inny blok.Ten przykład jest trywialny. Bardziej interesujące zastosowania to filtrowanie wszystkich elementów w tablicy:
Lub możemy również dostarczyć niestandardowy algorytm sortowania, na przykład na podstawie rozmiaru ciągu:
Mam nadzieję, że to pomoże ci lepiej to zrozumieć.
BTW, jeśli blok jest opcjonalny, powinieneś go nazwać:
Jeśli nie jest opcjonalny, po prostu go wywołaj.
EDYTOWAĆ
@hmak utworzył repl.it dla tych przykładów: https://repl.it/@makstaks/blocksandyieldsrubyexample
źródło
racsO
jeślithe_name = ""
"Oscar"
(nie jest bardzo jasne w odpowiedzi)person.do_with_name {|string| yield string, something_else }
W języku Ruby metody mogą sprawdzić, czy zostały wywołane w taki sposób, że oprócz zwykłych argumentów podano blok. Zwykle odbywa się to za pomocą
block_given?
metody, ale można również odwołać się do bloku jako jawnego Proc, poprzedzając znak ampersand (&
) przed ostateczną nazwą argumentu.Jeśli metoda jest wywoływana z blokiem, metoda może
yield
sterować blokiem (wywołać blok) z pewnymi argumentami, jeśli to konieczne. Rozważ tę przykładową metodę, która pokazuje:Lub używając specjalnej składni argumentu blokowego:
źródło
Całkiem możliwe, że ktoś udzieli tu naprawdę szczegółowej odpowiedzi, ale zawsze uważałem ten post Roberta Sosińskiego za doskonałe wyjaśnienie subtelności między blokami, procami i lambdami.
Powinienem dodać, że moim zdaniem post, do którego prowadzę link, jest specyficzny dla ruby 1.8. Niektóre rzeczy uległy zmianie w Ruby 1.9, na przykład zmienne blokowe są lokalne dla bloku. W wersji 1.8 otrzymasz coś takiego:
Podczas gdy 1.9 zapewni Ci:
Nie mam 1.9 na tym komputerze, więc powyższe może zawierać błąd.
źródło
Chciałem w pewnym sensie dodać, dlaczego tak robisz w odpowiedzi na i tak świetne odpowiedzi.
Nie mam pojęcia, z jakiego języka pochodzisz, ale zakładając, że jest to język statyczny, tego rodzaju rzeczy będą wyglądały znajomo. W ten sposób czytasz plik w Javie
Ignorując cały łańcuch związany z strumieniem, Chodzi o to
Tak to robisz w rubinie
Zupełnie inaczej. Rozbicie tego
Tutaj, zamiast zajmować się krokiem pierwszym i drugim, w zasadzie delegujesz to do innej klasy. Jak widać, radykalnie zmniejsza to ilość kodu, który musisz napisać, co ułatwia czytanie i zmniejsza ryzyko wycieków pamięci lub braku możliwości usunięcia blokad plików.
Teraz nie jest tak, że nie można zrobić czegoś podobnego w java, w rzeczywistości ludzie robią to od dziesięcioleci. To się nazywa wzór strategii . Różnica polega na tym, że bez bloków, w przypadku czegoś tak prostego jak przykład pliku, strategia staje się nadmierna z powodu ilości klas i metod, które musisz napisać. W przypadku bloków jest to tak prosty i elegancki sposób, aby to zrobić, że NIE ma sensu NIE strukturyzować kodu w ten sposób.
Nie jest to jedyny sposób, w jaki używane są bloki, ale inne (jak wzorzec Konstruktora, który można zobaczyć w form_for api w szynach) są na tyle podobne, że powinno być oczywiste, co się dzieje, gdy obejdziesz się tym. Kiedy widzisz bloki, zwykle bezpiecznie jest założyć, że wywołanie metody jest tym, co chcesz zrobić, a blok opisuje, jak chcesz to zrobić.
źródło
File.readlines("readfile.rb").each_with_index do |line, index| puts "#{index + 1}: #{line}" end
i śmiejmy się jeszcze mocniej z ludzi z Java.IO.foreach('readfile.rb').each_with_index { |line, index| puts "#{index}: #{line}" }
(plus brak problemów z pamięcią)Uważam, że ten artykuł jest bardzo przydatny. W szczególności następujący przykład:
co powinno dać następujące dane wyjściowe:
Zasadniczo za każdym razem, gdy zostanie wykonane wywołanie
yield
ruby, uruchomi kod wdo
bloku lub w środku{}
. Jeśli podano parametr,yield
to zostanie on podany jako parametr dodo
bloku.Dla mnie to był pierwszy raz, kiedy naprawdę zrozumiałem, co
do
robią bloki. Zasadniczo jest to sposób, w jaki funkcja umożliwia dostęp do wewnętrznych struktur danych, zarówno w celu iteracji, jak i konfiguracji funkcji.Kiedy więc w szynach piszesz:
Uruchomi to
respond_to
funkcję, która zwrócido
blok z parametrem (wewnętrznym)format
. Następnie wywołujesz.html
funkcję dla tej zmiennej wewnętrznej, co z kolei daje blok kodu do uruchomieniarender
polecenia. Pamiętaj, że.html
przyniesie to tylko wtedy, gdy jest to wymagany format pliku. (technicznie: te funkcje faktycznieblock.call
nie używają tego,yield
co widać ze źródła, ale funkcjonalność jest zasadniczo taka sama, zobacz to pytanie w celu omówienia.) Zapewnia to sposób, aby funkcja wykonała pewną inicjalizację, a następnie pobierała dane wejściowe z kodu wywołującego i następnie w razie potrzeby kontynuować przetwarzanie.Innymi słowy, jest podobny do funkcji przyjmującej anonimową funkcję jako argument, a następnie wywołującej ją w javascript.
źródło
W Ruby blok jest zasadniczo fragmentem kodu, który można przekazać i wykonać dowolną metodą. Bloki są zawsze używane z metodami, które zwykle przekazują im dane (jako argumenty).
Bloki są szeroko stosowane w klejnotach Ruby (w tym Railsach) oraz w dobrze napisanym kodzie Ruby. Nie są obiektami, dlatego nie można ich przypisywać do zmiennych.
Podstawowa składnia
Blok to fragment kodu ujęty w {} lub do..end. Zgodnie z konwencją w przypadku bloków jednowierszowych należy stosować składnię nawiasów klamrowych, aw przypadku bloków wieloliniowych należy stosować składnię do..end.
Każda metoda może otrzymać blok jako domyślny argument. Blok jest wykonywany przez instrukcję return w ramach metody. Podstawowa składnia to:
Po osiągnięciu instrukcji fedrowania metoda medytacji daje kontrolę nad blokiem, kod w bloku jest wykonywany, a kontrola jest zwracana do metody, która wznawia wykonywanie natychmiast po instrukcji fed.
Gdy metoda zawiera instrukcję dochodu, oczekuje otrzymania bloku w czasie wywołania. Jeśli blok nie zostanie podany, wyjątek zostanie zgłoszony po osiągnięciu instrukcji dochodu. Możemy uczynić blok opcjonalnym i uniknąć generowania wyjątku:
Nie można przekazać wielu bloków do metody. Każda metoda może otrzymać tylko jeden blok.
Zobacz więcej na: http://www.zenruby.info/2016/04/introduction-to-blocks-in-ruby.html
źródło
Czasami używam „wydajności” w ten sposób:
źródło
Logger
że użytkownik nie musi wykonywać jakiegoś zadania, jeśli użytkownik nie musi tego robić. Powinieneś jednak wyjaśnić swoje ...Mówiąc prościej, Yields pozwala, aby tworzona metoda przyjmowała i wywoływała bloki. Słowo kluczowe wydajności w szczególności jest miejscem, w którym zostaną wykonane „rzeczy” w bloku.
źródło
Chciałbym tu wspomnieć o dwóch kwestiach dotyczących wydajności. Po pierwsze, podczas gdy wiele odpowiedzi tutaj mówi o różnych sposobach przekazania bloku do metody wykorzystującej wydajność, porozmawiajmy również o przepływie sterowania. Jest to szczególnie istotne, ponieważ możesz dać WIELU CZASÓW blokowi. Spójrzmy na przykład:
Po wywołaniu każdej metody wykonuje się linia po linii. Teraz, gdy przejdziemy do bloku 3. razy, ten blok zostanie wywołany 3 razy. Za każdym razem, gdy wywołuje plon. Ta wydajność jest powiązana z blokiem związanym z metodą, która wywołała każdą metodę. Należy zauważyć, że za każdym razem, gdy wywoływana jest wydajność, zwraca kontrolę z powrotem do bloku każdej metody w kodzie klienta. Po zakończeniu wykonywania blok wraca do bloku 3. razy. I dzieje się to 3 razy. Tak więc blok w kodzie klienta jest wywoływany 3 odrębnymi okazjami, ponieważ fedrunek jest jawnie nazywany 3 oddzielnymi czasami.
Moja druga uwaga dotyczy enum_for i fed. enum_for tworzy instancję klasy Enumerator, a ten obiekt Enumerator odpowiada również na fed.
Zauważ więc, że za każdym razem, gdy wywołujemy rodzaje za pomocą zewnętrznego iteratora, wywoła to wydajność tylko raz. Następnym razem, gdy go nazwiemy, wywoła następną wydajność i tak dalej.
Jest ciekawa ciekawostka w odniesieniu do enum_for. Dokumentacja online zawiera następujące informacje:
Jeśli nie podasz symbolu jako argumentu dla enum_for, ruby podłączy moduł wyliczający do każdej metody odbiornika. Niektóre klasy nie mają każdej metody, na przykład klasa String.
Tak więc, w przypadku niektórych obiektów wywoływanych za pomocą enum_for, musisz wyraźnie określić, jaka będzie twoja metoda wyliczania.
źródło
Wydajność może być użyta jako blok bezimienny do zwrócenia wartości w metodzie. Rozważ następujący kod:
Możesz utworzyć metodę „W górę”, która ma przypisany jeden argument. Możesz teraz przypisać ten argument, aby uzyskać wynik, który wywoła i wykona powiązany blok. Możesz przypisać blok po liście parametrów.
Gdy wywołanie metody Up daje argument z argumentem, jest on przekazywany do zmiennej blokowej w celu przetworzenia żądania.
źródło