zrób..end vs curly szelki dla bloków w Ruby
Mam współpracownika, który aktywnie próbuje mnie przekonać, że nie powinienem używać do..koniec i zamiast tego użyj nawiasów klamrowych do definiowania bloków wielowierszowych w Ruby.
Jestem mocno w obozie tylko za pomocą kręconych szelek dla krótkich jednolinijek i zrobić..koniec na wszystko inne. Ale pomyślałem, że skontaktuję się z większą społecznością, aby uzyskać jakieś rozwiązanie. Więc co to jest i dlaczego? (Przykład jakiegoś kodu)context do
setup { do_some_setup() }
should "do somthing" do
# some more code...
end
end
Lub
context {
setup { do_some_setup() }
should("do somthing") {
# some more code...
}
}
[[2]} osobiście, po prostu patrząc na powyższe odpowiada na pytanie dla mnie, ale chciałem otworzyć to na większą społeczność. 13 answers
Ogólna Konwencja ma używać do..end for multi-line blocks and curly braces for single line blocks, but there is also a difference between the two that can be illustrated with this example:
puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil
Oznacza to, że {} ma wyższy priorytet niż do..koniec, więc miej to na uwadze przy podejmowaniu decyzji, czego chcesz użyć.
P. S: jeszcze jeden przykład, o którym należy pamiętać podczas rozwijania swoich preferencji.
Następujący kod:
task :rake => pre_rake_task do
something
end
Naprawdę oznacza:
task(:rake => pre_rake_task){ something }
I ten kod:
task :rake => pre_rake_task {
something
}
Naprawdę oznacza:
task :rake => (pre_rake_task { something })
Więc aby uzyskać rzeczywistą definicję, którą chcesz, z klamrami kręconymi, musisz zrobić: {]}
task(:rake => pre_rake_task) {
something
}
Może używanie szelek do parametrów jest czymś, co i tak chcesz zrobić, ale jeśli tego nie robisz, prawdopodobnie najlepiej jest użyć do..Zakończ w tych przypadkach, aby uniknąć tego zamieszania.
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
2011-04-07 20:57:46
From Programowanie Ruby :
Szelki mają wysoki priorytet; do ma niski priorytet. Jeśli wywołanie metody ma parametry, które nie są zamknięte w nawiasach, nawiasowa forma bloku będzie wiązać się z ostatnim parametrem, a nie z ogólnym wywołaniem. Formularz do wiąże się z wywołaniem.
Więc kod
f param {do_something()}
Wiąże blok ze zmienną param
podczas gdy kod
f param do do_something() end
Wiąże blok z funkcją f
.
Jednak nie jest to problemem, jeśli w nawiasie umieścisz argumenty funkcji.
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
2011-04-07 20:43:24
Jest kilka punktów widzenia na ten temat, to naprawdę kwestia osobistych preferencji. Wielu rubyistów przyjmuje takie podejście jak ty. Jednak dwa inne style, które są wspólne, to zawsze używać jednego lub drugiego, lub używać {[0] } dla bloków, które zwracają wartości, i do ... end
dla bloków, które są wykonywane dla efektów ubocznych.
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
2011-04-07 20:38:51
Jest jedna zasadnicza zaleta nawiasów klamrowych-wiele edytorów ma znacznie łatwiejszy czas dopasowania, co znacznie ułatwia niektóre rodzaje debugowania. Tymczasem słowo kluczowe " do...koniec "jest nieco trudniejszy do dopasowania, zwłaszcza, że "koniec" jest również dopasowany "Jeśli".
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
2011-11-09 20:41:17
Głosuję na do / end
Konwencja jest do .. end
dla wielowierszowych i { ... }
dla jednowierszowych.
Ale ja wolę do .. end
, więc jak mam jedną linijkę, to i tak używam do .. end
, ale formatuję ją jak zwykle Dla do / end w trzech linijkach. To sprawia, że wszyscy są szczęśliwi.
10.times do
puts ...
end
Jeden problem z { }
polega na tym, że jest to poezja-mode-wrogie (ponieważ wiążą się ściśle z ostatnim parametrem, a nie całym wywołaniem metody, więc musisz dołączyć parens metody) i po prostu, moim zdaniem, nie wyglądaj tak ładnie. Nie są to grupy twierdzeń i zderzają się ze stałymi hash dla czytelności.
Plus, widziałem dość { }
w programach C. Sposób Ruby, jak zwykle, jest lepszy. Istnieje dokładnie jeden typ if
bloku i nigdy nie musisz wracać i konwertować instrukcji do instrukcji złożonej.
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
2011-04-07 23:08:34
Najczęściej spotykaną zasadą jaką widziałem (ostatnio w elokwentny Ruby ) jest:
- jeśli jest to blok wielowierszowy, użyj do / end
- jeśli jest to pojedynczy blok liniowy, użyj {}
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
2011-04-07 20:42:31
Kilka wpływowych rubyistów sugeruje, aby używać szelek, gdy używasz zwracanej wartości, i robić / kończyć, gdy tego nie robisz.
Http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace (on archive.org)
Http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc (on archive.org)
Wydaje się to dobrą praktyką w ogóle.
Zmodyfikowałbym nieco tę zasadę, aby powiedzieć, że należy unikać używania do / end na pojedynczej linii, ponieważ jest trudniej czytać.
Musisz być bardziej ostrożny używając szelek, ponieważ będzie to wiązać się z ostatnim param metody zamiast całego wywołania metody. Wystarczy dodać nawiasy, aby tego uniknąć.
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-03-27 21:00:01
Sprowadza się do osobistych uprzedzeń, wolę nawiasy klamrowe niż blok do / end, ponieważ jest bardziej zrozumiały dla większej liczby programistów, ponieważ większość języków tła używa ich w konwencji do / end. Biorąc to pod uwagę, prawdziwym kluczem jest dojść do Porozumienia w Twoim sklepie, jeśli do / end jest używany przez programistów 6/10, niż wszyscy powinni ich używać, jeśli 6/10 używa kręconych szelek, a następnie trzymać się tego paradygmatu.
Its all about making a pattern so that the team as a whole can szybciej identyfikuj struktury kodu.
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
2011-04-07 20:37:58
Istnieje subtelna różnica między nimi, ale {} wiąże się mocniej niż do/end.
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
2011-04-07 20:38:51
W rzeczywistości jest to osobiste preferencje, ale powiedziawszy to, przez ostatnie 3 lata moich doświadczeń z ruby nauczyłem się, że ruby ma swój styl.
Jednym z przykładów może być , jeśli korzystasz z tła Javy, dla metody boolean możesz użyć
def isExpired
#some code
end
Zwróć uwagę na przypadek wielbłąda i najczęściej przedrostek "is", aby zidentyfikować go jako metodę logiczną.
Ale w świecie ruby, ta sama metoda byłaby
def expired?
#code
end
Więc osobiście uważam, że lepiej wybrać 'ruby way' (Ale wiem, że potrzeba trochę czasu, aby zrozumieć (Zajęło mi to około 1 roku: D)).
W końcu wybrałbym
do
#code
end
Bloki.
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
2011-04-10 22:46:47
Umieściłem inną odpowiedź, chociaż duża różnica była już wskazana (prcedence/binding), a to może powodować trudne do znalezienia problemy (blaszany człowiek i inni na to wskazywali). Myślę, że mój przykład pokazuje problem z nie tak zwykłym fragmentem kodu, nawet doświadczeni programiści nie czytają jak sunday times: {]}
module I18n
extend Module.new {
old_translate=I18n.method(:translate)
define_method(:translate) do |*args|
InplaceTrans.translate(old_translate, *args)
end
alias :t :translate
}
end
module InplaceTrans
extend Module.new {
def translate(old_translate, *args)
Translator.new.translate(old_translate, *args)
end
}
end
Potem zrobiłem trochę kodu upiększającego ...
#this code is wrong!
#just made it 'better looking'
module I18n
extend Module.new do
old_translate=I18n.method(:translate)
define_method(:translate) do |*args|
InplaceTrans.translate(old_translate, *args)
end
alias :t :translate
end
end
Jeśli zmienisz {}
tutaj na do/end
otrzymasz błąd, ta metoda translate
robi nie istnieje ...
Dlaczego tak się dzieje, wskazuje się tutaj więcej niż jeden-pierwszeństwo. Ale gdzie tu umieścić aparat ortodontyczny? @ blaszany: ja zawsze używam aparatów ortodontycznych, tak jak ty, ale tutaj ... nadzorowane)
Więc każda odpowiedź jak
If it's a multi-line block, use do/end If it's a single line block, use {}
Is just wrong if used without the " BUT Keep an eye on braces / precedence!"
Jeszcze raz:
extend Module.new {} evolves to extend(Module.new {})
I
extend Module.new do/end evolves to extend(Module.new) do/end
(co wynik extend robi z blokiem ...)
Więc jeśli chcesz użyć do / end use this:
#this code is ok!
#just made it 'better looking'?
module I18n
extend(Module.new do
old_translate=I18n.method(:translate)
define_method(:translate) do |*args|
InplaceTrans.translate(old_translate, *args)
end
alias :t :translate
end)
end
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
2014-07-11 10:40:29
Moim osobistym stylem jest podkreślanie czytelności nad sztywnymi zasadami {
...}
vs do
...end
Wybór, gdy taki wybór jest możliwy. Moja idea czytelności jest następująca:
[ 1, 2, 3 ].map { |e| e + 1 } # preferred
[ 1, 2, 3 ].map do |e| e + 1 end # acceptable
[ 1, 2, 3 ].each_with_object [] do |e, o| o << e + 1 end # preferred, reads like a sentence
[ 1, 2, 3 ].each_with_object( [] ) { |e, o| o << e + 1 } # parens make it less readable
Foo = Module.new do # preferred for a multiline block, other things being equal
include Comparable
end
Foo = Module.new { # less preferred
include Comparable
}
Foo = Module.new { include Comparable } # preferred for a oneliner
Foo = module.new do include Comparable end # imo less readable for a oneliner
[ [ 1 ], [ 1, 2 ] ].map { |e| e.map do |e| e + 1 end } # slightly better
[ [ 1 ], [ 1, 2 ] ].map { |e| e.map { |e| e + 1 } } # slightly worse
W bardziej złożonej składni, takiej jak Wielowierszowe zagnieżdżone bloki, staram się przeplatać {
...}
i do
...end
ograniczniki dla większości naturalnych wyników, np.
Foo = Module.new {
if true then
Bar = Module.new { # I intersperse {} and keyword delimiters
def quux
"quux".tap do |string| # I choose not to intersperse here, because
puts "(#{string.size} characters)" # for multiline tap, do ... end in this
end # case still loks more readable to me.
end
}
end
}
Chociaż brak sztywnych reguł może spowodować, że różne opcje dla różnych programistów będą sprytnie różne, uważam, że każdy przypadek optymalizacja pod kątem czytelności, choć subiektywna, to zysk netto nad przestrzeganiem sztywnych zasad.
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
2014-08-03 14:25:47
Jest trzecia opcja: napisz preprocesor, aby wywnioskować "koniec" na własnej linii, z wcięcia. Głęboko myślący, którzy wolą zwięzły kod, mają rację.
Jeszcze lepiej, hack ruby więc jest to flaga.
Oczywiście najprostszym rozwiązaniem" pick your fights " jest przyjęcie konwencji stylu, zgodnie z którą Sekwencja końców pojawia się w tej samej linii i nauczenie kolorowania składni, aby je wyciszyć. Dla ułatwienia edycji, można użyć skryptów edytora, aby rozwinąć/zwinąć te sekwencje.
20% do 25% moich wierszy kodu ruby kończy się na ich własnej linii, wszystkie trywialnie wywnioskowane przez moje konwencje wcięć. Ruby jest językiem podobnym do Lispu, który osiągnął największy sukces. Kiedy ludzie kwestionują to, pytając, gdzie są wszystkie upiorne nawiasy, pokazuję im funkcję ruby kończącą się na siedmiu liniach zbędnego "końca".
Przez lata robiłem kod używając preprocesora Lispu, aby wywnioskować większość nawiasów: Pasek ' / ' otworzył grupę, która autoklazła się na końcu linia, A znak dolara " $ " służył jako pusty element zastępczy, w którym w przeciwnym razie nie byłoby symboli pomagających wnioskować o grupach. To oczywiście terytorium wojny religijnej. Lisp / scheme bez nawiasów jest najbardziej poetycki ze wszystkich języków. Jednak łatwiej jest po prostu wyciszyć nawiasy za pomocą kolorowania składni.
Nadal koduję z preprocesorem dla Haskell, aby dodać heredocs i domyślnie wszystkie linie spłukiwania jako komentarze, wszystko wcięte jako kod. Nie lubię komentarzy, bez względu na język.
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-29 22:06:08