do..end 与 Ruby 中块的花括号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5587264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:52:39  来源:igfitidea点击:

do..end vs curly braces for blocks in Ruby

ruby-on-railsrubyruby-on-rails-3coding-style

提问by Blake Taylor

I have a coworker who is actively trying to convince me that I should not use do..end and instead use curly braces for defining multiline blocks in Ruby.

我有一个同事积极地试图说服我,我不应该使用 do..end 而是使用花括号在 Ruby 中定义多行块。

I'm firmly in the camp of only using curly braces for short one-liners and do..end for everything else. But I thought I would reach out to the greater community to get some resolution.

我坚定地站在只对短单行使用花括号的阵营中,并做..结束其他所有事情。但我想我会与更大的社区联系以获得一些解决方案。

So which is it, and why? (Example of some shoulda code)

那么它是哪个,为什么?(一些应该代码的例子)

context do
  setup { do_some_setup() }
  should "do somthing" do
    # some more code...
  end
end

or

或者

context {
  setup { do_some_setup() }
  should("do somthing") {
    # some more code...
  }
}

Personally, just looking at the above answers the question for me, but I wanted to open this up to the greater community.

就我个人而言,仅看上述内容就可以回答我的问题,但我想向更大的社区开放。

回答by Pan Thomakos

The general convention is to use 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:

一般约定是对多行块使用 do..end ,对单行块使用花括号,但两者之间也有区别,可以用这个例子来说明:

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

This means that {} has a higher precedence than do..end, so keep that in mind when deciding what you want to use.

这意味着 {} 的优先级高于 do..end,因此在决定要使用的内容时请记住这一点。

P.S: One more example to keep in mind while you develop your preferences.

PS:在您制定偏好时要记住的另一个例子。

The following code:

以下代码:

task :rake => pre_rake_task do
  something
end

really means:

真正意思:

task(:rake => pre_rake_task){ something }

And this code:

而这段代码:

task :rake => pre_rake_task {
  something
}

really means:

真正意思:

task :rake => (pre_rake_task { something })

So to get the actual definition that you want, with curly braces, you must do:

因此,要使用花括号获得您想要的实际定义,您必须执行以下操作:

task(:rake => pre_rake_task) {
  something
}

Maybe using braces for parameters is something you want to do anyways, but if you don't it's probably best to use do..end in these cases to avoid this confusion.

也许使用大括号作为参数是您无论如何都想做的事情,但是如果您不这样做,最好在这些情况下使用 do..end 以避免这种混淆。

回答by David Brown

From Programming Ruby:

编程 Ruby

Braces have a high precedence; do has a low precedence. If the method invocation has parameters that are not enclosed in parentheses, the brace form of a block will bind to the last parameter, not to the overall invocation. The do form will bind to the invocation.

大括号具有很高的优先级;do 的优先级很低。如果方法调用具有未括在括号中的参数,则块的大括号形式将绑定到最后一个参数,而不是整个调用。do 表单将绑定到调用。

So the code

所以代码

f param {do_something()}

Binds the block to the paramvariable while the code

param将代码块绑定到变量

f param do do_something() end

Binds the block to the function f.

将块绑定到函数f

However this is a non-issue if you enclose function arguments in parenthesis.

但是,如果您将函数参数括在括号中,则这不是问题。

回答by GSto

There a few points of view on this, it's really a matter of personal preference. Many rubyists take the approach you do. However, two other styles that are common is to always use one or the other, or to use {}for blocks that return values, and do ... endfor blocks that are executed for side effects.

关于这个有几个观点,这真的是个人喜好的问题。许多 ruby​​ 专家采用您的方法。但是,另外两种常见的样式是始终使用一种或另一种,或者{}用于返回值do ... end的块,以及用于执行副作用的块。

回答by GlyphGryph

There is one major benefit to curly braces - many editors have a MUCH easier time of matching them, making certain types of debugging much easier. Meanwhile, the keyword "do...end" is quite a bit harder to match, especially since "end"s also match "if"s.

花括号有一个主要好处——许多编辑器可以更轻松地匹配它们,从而使某些类型的调试更容易。同时,关键字“do...end”很难匹配,特别是因为“end”也匹配“if”。

回答by Peter Brown

The most common rule I've seen (most recently in Eloquent Ruby) is:

我见过的最常见的规则(最近在Eloquent Ruby 中)是:

  • If it's a multi-line block, use do/end
  • If it's a single line block, use {}
  • 如果是多行块,请使用 do/end
  • 如果是单行块,请使用 {}

回答by DigitalRoss

I'm voting for do / end

我投票给做/结束



The convention is do .. endfor multiline and { ... }for one-liners.

约定适用do .. end于多行和{ ... }单行。

But I like do .. endbetter, so when I have a one liner, I use do .. endanyway but format it as usual for do/end in three lines. This makes everyone happy.

但我do .. end更喜欢,所以当我有一个单行时,我do .. end无论如何都会使用,但像往常一样将它格式化为三行。这让每个人都很高兴。

  10.times do 
    puts ...
  end

One problem with { }is that it is poetry-mode-hostile (because they bind tightly to the last parameter and not the entire method call, so you must include method parens) and they just, to my mind, don't look as nice. They are not statement-groups and they clash with hash constants for readability.

一个问题{ }是它是诗歌模式敌对的(因为它们紧紧地绑定到最后一个参数而不是整个方法调用,所以你必须包含方法括号),而且在我看来,它们看起来不太好。它们不是语句组,它们与散列常量冲突以提高可读性。

Plus, I've seen enough of { }in C programs. Ruby's way, as usual, is better. There is exactly one type of ifblock, and you never have to go back and convert a statement into a compound-statement.

另外,我已经{ }在 C 程序中看到了足够多的内容。像往常一样,Ruby 的方式更好。只有一种类型的if块,您永远不必返回并将语句转换为复合语句。

回答by Kelvin

A couple influential rubyists suggest to use braces when you use the return value, and do/end when you don't.

一些有影响力的 ruby​​ists 建议在使用返回值时使用大括号,不使用时使用 do/end。

http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace(on archive.org)

http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace(在archive.org上)

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc(on archive.org)

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc(在 archive.org 上)

This seems like a good practice in general.

总的来说,这似乎是一个很好的做法。

I'd modify this principle a bit to say that you should avoid using do/end on a single line because it's harder to read.

我会稍微修改一下这个原则,说你应该避免在一行中使用 do/end,因为它更难阅读。

You do have to be more careful using braces because it'll bind to a method's final param instead of the whole method call. Just add parentheses to avoid that.

使用大括号必须更加小心,因为它会绑定到方法的最终参数而不是整个方法调用。只需添加括号即可避免这种情况。

回答by sameera207

Actually it's a personal preference, but having said that, for past 3 years of my ruby experiences what I have learnt is that ruby has its style.

其实这是个人喜好,不过话说回来,在过去 3 年的 ruby​​ 经历中,我学到的是 ruby​​ 有它的风格。

One example would be, if you are comming from a JAVA background , for a boolean method you might use

一个例子是,如果您来自 JAVA 背景,对于您可能使用的布尔方法

def isExpired
  #some code
end 

notice the camel case and most often 'is' prefix to identify it as a boolean method.

请注意驼峰式大小写和最常见的“is”前缀,以将其标识为布尔方法。

But in ruby world, the same method would be

但在 ruby​​ 世界中,同样的方法是

def expired?
  #code
end

so I personally think, it's better to go with 'ruby way' (But I know it takes some time for one to understand (it took me around 1 year :D)).

所以我个人认为,最好采用“红宝石方式”(但我知道需要一些时间才能理解(我花了大约 1 年时间:D))。

Finally, I would go with

最后,我会和

do 
  #code
end

blocks.

块。

回答by halfbit

I put another Answer, although the bigdifference was already pointed out (prcedence/binding), and that can cause hard to find problems (the Tin Man, and others pointed that out). I think my example shows the problem with a not so usual code snippet, even experienced programmeres do not read like the 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

Then i did some code beautifying ...

然后我做了一些代码美化...

#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

if you change the {}here to do/endyou will get the error, that method translatedoes not exist ...

如果您将{}此处更改为do/end您将收到错误,该方法translate不存在...

Why this happens is pointed out here more than one - precedence. But where to put braces here? (@the Tin Man: I always use braces, like you, but here ... overseen)

为什么会发生这种情况,这里不止一个指出 - 优先级。但是在哪里放大括号呢?(@铁皮人:我总是像你一样使用大括号,但在这里......监督)

so every answer like

所以每个答案都像

If it's a multi-line block, use do/end
If it's a single line block, use {}
If it's a multi-line block, use do/end
If it's a single line block, use {}

is just wrongif used without the "BUT Keep an eye on braces / precedence!"

如果在没有“但请注意大括号/优先级!”的情况下使用是错误的

again:

再次:

extend Module.new {} evolves to extend(Module.new {})

and

extend Module.new do/end evolves to extend(Module.new) do/end

(what ever the result of extend does with the block ...)

(extend 的结果对块做了什么......)

So if you want to use do/end use this:

所以如果你想使用 do/end 使用这个:

#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

回答by Jake Kalstad

Comes down to personal bias, I prefer curly braces over a do/end block as its more understandable to a higher number of developers due to a majority of background languages use them over the do/end convention. With that being said the real key is to come to an agreement within your shop, if do/end is used by 6/10 developers than EVERYONE should be using them, if 6/10 use curly braces, then stick to that paradigm.

归结为个人偏见,我更喜欢花括号而不是 do/end 块,因为它对更多的开发人员来说更容易理解,因为大多数背景语言在 do/end 约定上使用它们。话虽如此,真正的关键是在您的商店内达成一致,如果 6/10 的开发人员使用 do/end,而不是每个人都应该使用它们,如果 6/10 使用花括号,则坚持该范例。

Its all about making a pattern so that the team as a whole can identify the code structures quicker.

一切都是为了制作一个模式,以便整个团队可以更快地识别代码结构。