使用块vs括号{}
新的ruby,戴上你的新手套。
以下两个片段之间有什么区别(模糊或实际)?
my_array = [:uno, :dos, :tres] my_array.each { |item| puts item } my_array = [:uno, :dos, :tres] my_array.each do |item| puts item end
我意识到括号语法将允许您将块放在一行
my_array.each { |item| puts item }
但除此之外,是否有任何令人信服的理由使用一种语法?
Ruby的食谱说支架语法比do..end
具有更高的优先顺序
请记住,括号语法比do..end语法具有更高的优先级。 考虑以下两个代码片段:
1.upto 3 do |x| puts x end 1.upto 3 { |x| puts x } # SyntaxError: compile error
第二个例子只有在括号被使用时才起作用, 1.upto(3) { |x| puts x }
1.upto(3) { |x| puts x }
这是一个有点老的问题,但我想尝试解释一些关于{}
并do .. end
就像之前所说的那样
括号语法比do..end具有更高的优先顺序
但是这个如何改变:
method1 method2 do puts "hi" end
在这种情况下,将使用do..end
块调用method1,并将method2作为parameter passing给method1! 相当于method1(method2){ puts "hi" }
但如果你说
method1 method2{ puts "hi" }
那么method2将被调用,然后返回的值将作为parameter passing给method1。 这相当于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 }
####输出####
#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
一般来说,惯例是在你做一个小的操作时使用{}
,例如方法调用或比较等等,所以这是非常有意义的:
some_collection.each { |element| puts element }
但是,如果你有一些稍微复杂的逻辑去多行,那么使用do .. end
就像:
1.upto(10) do |x| add_some_num = x + rand(10) puts '*' * add_some_num end
基本上,如果你的块逻辑去多行,不能安装在同一行,那么使用do .. end
,如果你的块逻辑是简单的,只是一个简单的/单行的代码,然后使用{}
。
Ruby中有两种常见的selectdo end
和{ }
的方式:
第一个也是非常常见的风格是Ruby on Rails所普及的,它基于单线和多线的简单规则:
- 使用大括号
{ }
作为单行块 - 使用
do end
多行块
这是有道理的,因为do / end在一行中严重读取,但是对于多行块,在其自己的行上留下一个闭合的结尾与使用ruby end
所有其他内容不一致,例如模块,类和方法定义( def
等)和控制结构( if
, while
, case
等)
第二种不太常见的风格被称为语义,或由已故的伟大的ruby吉姆·维里奇(Jim Weirich)提出的“ Weirich Braces ”:
- 使用
do end
程序块 - 使用大括号
{ }
作为功能块
这意味着当块被评估为返回值时 ,它应该是可链接的,并且{}
括号对于方法链接更有意义。
另一方面,当块被评估为副作用时 ,返回值是无关紧要的,块只是“做”了某些东西,所以被链接是没有意义的。
语法上的这种区分传达了关于块的评估的视觉意义,以及是否应该关心它的返回值。
例如,这里块的返回值应用于每个项目:
items.map { |i| i.upcase }
但是,这里没有使用块的返回值。 它在程序上运行,并且对它做一个副作用:
items.each do |item| puts item end
语义风格的另一个好处是你不需要改变大括号来做/结束,只是因为一个行被添加到块中。
作为一个观察,巧合的function块通常是单线的, 程序块(例如configuration)是多线的。 所以,遵循Weirich风格最终看起来几乎和Rails风格一样。