对于Ruby中的块,执行.对比花括号

Bla*_*lor 139 ruby coding-style ruby-on-rails ruby-on-rails-3

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

我坚定地只使用花括号作为短单线,并且做其他事情.但我想我会联系更大的社区来获得一些解决方案.

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

context do
  setup { do_some_setup() }
  should "do somthing" do
    # some more code...
  end
end
Run Code Online (Sandbox Code Playgroud)

要么

context {
  setup { do_some_setup() }
  should("do somthing") {
    # some more code...
  }
}
Run Code Online (Sandbox Code Playgroud)

就个人而言,只看上面的问题就可以解答我的问题,但我想向更大的社区开放.

Pan*_*kos 235

一般约定是将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
Run Code Online (Sandbox Code Playgroud)

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

PS:在开发偏好时要记住的另一个例子.

以下代码:

task :rake => pre_rake_task do
  something
end
Run Code Online (Sandbox Code Playgroud)

真正意思:

task(:rake => pre_rake_task){ something }
Run Code Online (Sandbox Code Playgroud)

这段代码:

task :rake => pre_rake_task {
  something
}
Run Code Online (Sandbox Code Playgroud)

真正意思:

task :rake => (pre_rake_task { something })
Run Code Online (Sandbox Code Playgroud)

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

task(:rake => pre_rake_task) {
  something
}
Run Code Online (Sandbox Code Playgroud)

也许使用大括号作为参数是你想要做的事情,但如果你不这样做,最好在这些情况下使用do..end来避免这种混乱.

  • 我投票总是在方法参数周围使用括号来回避整个问题. (43认同)
  • 这对我来说是一个老派的编程习惯.如果语言支持括号,我使用它们. (9认同)
  • +1表示优先级问题.当我尝试转换时,我有时会遇到意外的异常; 结束{} (8认同)
  • 为什么`puts [1,2,3].map 做|k| k+1; end` 只打印枚举器,即一件事。不是 puts 在这里传递了两个参数,即 `[1,2,3].map` 和 `do |k| k+1; 结束`? (2认同)
  • @ben:确切地说,因为是 `puts` 获得了两个参数。首先对 `.map` 求值,但它没有得到一个块(因为看起来像块的东西不是 `.map` 的参数),所以它返回一个枚举器,它成为 `puts` 第一个参数。`puts` 会将该块作为第二个参数,但 `puts` 不使用任何传递的块,因此什么也不会发生。括号解决了这个问题:`puts([1,2,3].map do |k| k+1; end)` (2认同)

Dav*_*own 51

来自编程Ruby:

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

所以代码

f param {do_something()}
Run Code Online (Sandbox Code Playgroud)

param在代码中将块绑定到变量

f param do do_something() end
Run Code Online (Sandbox Code Playgroud)

将块绑定到函数f.

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

  • +1"但是,如果将函数参数括在括号中,则这不是问题." 我这样做是为了习惯,而不是依靠机会和翻译的心血来潮.:-) (7认同)
  • @theTinMan,如果你的翻译在解析器中使用机会,你需要一个新的解释器. (4认同)
  • @PaulDraper - 确实如此,但并非所有语言都同意这个问题。但是(我认为)括号不“完成其工作”的情况非常罕见,因此使用括号普遍可以使您不必记住语言设计者做出的“随机”决定 - 即使它们是由编译器和解释器的实现者忠实执行的。 (2认同)

GSt*_*Sto 14

对此有几点看法,这实际上是个人偏好的问题.许多rubyists采取你做的方法.但是,另外两种常见的样式是始终使用其中一种,或者{}用于返回值do ... end的块,以及用于副作用的块.

  • 这不仅仅是个人喜好的问题。如果方法参数未包含在括号中,则参数绑定可能会导致细微的错误。 (2认同)

Gly*_*yph 8

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

  • 虽然我确实更喜欢大括号,但我认为编辑器没有理由很难找到 2/3 字符串而不是单个字符。尽管存在大多数编辑器已经匹配大括号的论点,而 `do ... end` 是一种特殊情况,需要特定于语言的逻辑。 (2认同)

Pet*_*own 7

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

  • 如果是多行块,请使用do/end
  • 如果是单行块,请使用{}


Dig*_*oss 7

我投票支持do/end


该惯例适用do .. end于多线和{ ... }单线.

但是我喜欢do .. end更好,所以当我有一个衬垫时,do .. end无论如何都会使用它,但是像往常一样将它格式化为三行中的do/end.这让每个人都开心.

  10.times do 
    puts ...
  end
Run Code Online (Sandbox Code Playgroud)

一个问题{ }是它是诗歌模式 - 敌对(因为它们紧紧地绑定到最后一个参数,而不是整个方法调用,所以你必须包括方法parens),在我看来,它们看起来并不那么好看.它们不是语句组,它们与哈希常量冲突以便于阅读.

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

  • 那么,如果我们喜欢 C 中的 { },那是否意味着我们也应该在 Ruby 中使用它们? (3认同)
  • "我在C程序中看到了足够多的{}和Perl.并且,在那里有几个陈述的+1,并且提倡Ruby的类似zen的编码风格.:-) (2认同)

Kel*_*vin 5

一些有影响力的rubyists建议在使用返回值时使用大括号,而在不使用时使用/ end.

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

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

这似乎是一般的好习惯.

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

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