Używanie do block vs nawiasy {}

Nowy w ruby, Załóż nowe rękawiczki.

Czy jest jakaś różnica (niejasna lub praktyczna) między poniższymi dwoma fragmentami?

my_array = [:uno, :dos, :tres]
my_array.each { |item| 
    puts item
}

my_array = [:uno, :dos, :tres]
my_array.each do |item| 
    puts item
end

Zdaję sobie sprawę, że składnia nawiasu pozwala na umieszczenie bloku w jednej linii

my_array.each { |item| puts item }

Ale poza tym, czy są jakieś przekonujące powody, aby używać jednej składni nad drugą?

Author: Mohsen Nosratinia, 2010-01-23

4 answers

Ruby cookbook mówi, że składnia nawiasu ma wyższy priorytet niż do..end

Należy pamiętać, że składnia nawiasów ma wyższy priorytet niż zrób..koniec składni. Rozważ następujące kwestie dwa fragmenty kodu:

1.upto 3 do |x|
  puts x
end

1.upto 3 { |x| puts x }
# SyntaxError: compile error

Drugi przykład działa tylko wtedy, gdy używane są nawiasy, 1.upto(3) { |x| puts x }

 97
Author: YOU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-23 10:17:51

To trochę stare pytanie, ale chciałbym spróbować wyjaśnić nieco więcej na temat {} i do .. end

Jak to jest powiedziane przed

Składnia nawiasu ma wyższy priorytet niż do..end

Ale jak ta robi różnicę:

method1 method2 do
  puts "hi"
end

W tym przypadku, method1 zostanie wywołana z blokiem do..end, A method2 zostanie przekazana do method1 jako argument! co jest równoważne method1(method2){ puts "hi" }

Ale jeśli powiesz

method1 method2{
  puts "hi"
}

Wtedy method2 będzie wywołane z blokiem, wtedy zwrócona wartość zostanie przekazana do method1 jako argument. Co jest równoważne method1(method2 do puts "hi" end)

def method1(var)
    puts "inside method1"
    puts "method1 arg = #{var}"
    if block_given?
        puts "Block passed to method1"
        yield "method1 block is running"
    else
        puts "No block passed to method1"
    end
end

def method2
    puts"inside method2"
    if block_given?
        puts "Block passed to method2"
        return yield("method2 block is running")
    else
        puts "no block passed to method2"
        return "method2 returned without block"
    end
end

#### test ####

method1 method2 do 
    |x| puts x
end

method1 method2{ 
    |x| puts x
}

#### output # # # #

#inside method2
#no block passed to method2
#inside method1
#method1 arg = method2 returned without block
#Block passed to method1
#method1 block is running

#inside method2
#Block passed to method2
#method2 block is running
#inside method1
#method1 arg = 
#No block passed to method1
 61
Author: bkdir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-14 20:13:50

Ogólnie, konwencją jest użycie {}, gdy wykonujesz małą operację, na przykład wywołanie metody lub porównanie, itp. więc to ma sens:

some_collection.each { |element| puts element }

Ale jeśli masz nieco skomplikowaną logikę, która przechodzi do wielu linii, użyj do .. end Jak:

1.upto(10) do |x|
  add_some_num = x + rand(10)
  puts '*' * add_some_num
end

Zasadniczo sprowadza się to do tego, że jeśli twoja logika blokowa przechodzi do wielu linii i nie może być zamontowana w tej samej linii, użyj do .. end i jeśli twoja logika blokowa jest prosta i tylko prosta / pojedyncza linia kodu, użyj {}.

 39
Author: nas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 16:17:31

Istnieją dwa wspólne style wyboru do end vs. { } dla bloków w Rubim:

Pierwszy i bardzo popularny styl został spopularyzowany przez Ruby on Rails i opiera się na prostej zasadzie jedno-i wielowierszowej:

  • użyj szelek { } dla bloków jednoliniowych
  • Użyj do end dla bloków wielowierszowych

Ma to sens, ponieważ do / end czyta się źle w jednowierszowej, ale w przypadku bloków wielowierszowych pozostawienie zamknięcia } wiszącego na własnej linii jest niezgodne z Wszystko inne, co używa end w Rubim, takie jak definicje modułów, klas i metod (def itd.) i struktur kontrolnych(if, while, case, itd.)

W 2004 roku, po raz pierwszy w Polsce, w Polsce i za granicą, w 2006 roku, w Polsce i za granicą, w 2009 roku, w Polsce i za granicą, w 2009 roku, w Polsce i za granicą.]}
  • Użyj do end dla bloków proceduralnych
  • użyj szelek { } do bloków funkcjonalnych

Oznacza to, że gdy blok zostanie oceniony dla jego return wartość , powinna być łańcuchowa, a szelki {} mają większy sens dla metody łańcuchowania.

Z drugiej strony, gdy blok jest oceniany pod kątem efektów ubocznych , to zwracana wartość nie ma znaczenia, a blok po prostu coś "robi", więc nie ma sensu być przykuty łańcuchem.

To rozróżnienie w składni przekazuje wizualne znaczenie dotyczące oceny bloku i tego, czy powinieneś dbać o jego zwracaną wartość.

Dla przykład, tutaj wartość zwracana bloku jest zastosowana do każdego elementu:

items.map { |i| i.upcase }

Tutaj jednak nie używa się zwracanej wartości bloku. To działa proceduralnie, i robi efekt uboczny z nim:

items.each do |item|
  puts item
end

Kolejną zaletą stylu semantycznego jest to, że nie trzeba zmieniać nawiasów, aby wykonać/zakończyć tylko dlatego, że linia została dodana do bloku.

Jako spostrzeżenie, przypadkowo funkcjonalne bloki są często Jednowierszowe, a proceduralne bloki (np. config) są Wielowierszowe. Tak więc podążanie za stylem Weirich kończy się wyglądem prawie takim samym jak styl Rails.

 4
Author: Andrew Vit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-02 23:56:05