使用do block vs braces {}
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用do block vs braces {}相关的知识,希望对你有一定的参考价值。
新的红宝石,穿上你的新手套。
以下两个片段之间是否有任何区别(模糊或实用)?
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 cookbook说括号语法的优先顺序高于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 }
这是一个有点老问题,但我想尝试解释一下{}
和do .. end
就像以前说过的那样
括号语法的优先顺序高于do..end
但这个如何有所作为:
method1 method2 do
puts "hi"
end
在这种情况下,将使用do..end
块调用method1,并将method2作为参数传递给method1!这相当于method1(method2){ puts "hi" }
但如果你说
method1 method2{
puts "hi"
}
然后使用块调用method2,然后返回的值将作为参数传递给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
}
#### 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
通常,惯例是在进行小操作时使用{}
,例如方法调用或比较等,所以这很有意义:
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中为块选择do end
和{ }
有两种常见的样式:
第一个也是非常常见的样式是由Ruby on Rails推广的,它基于单行与多行的简单规则:
- 使用大括号
{ }
作为单行块 - 将
do end
用于多行块
这是有道理的,因为do / end在单行中读取很差,但是对于多行块,留下一个关闭的}
挂在它自己的行上与在ruby中使用end
的所有其他内容不一致,例如模块,类和方法定义(def
等)和控制结构(if
,while
,case
等)
第二种不太常见的风格被称为语义,或称为“Weirich Braces”,由已故的伟大的红宝石家吉姆威尔希提出:
- 使用
do end
作为程序块 - 使用大括号
{ }
作为功能块
这意味着当评估块的返回值时,它应该是可链接的,并且{}
括号对于方法链更有意义。
另一方面,当评估块的副作用时,返回值无关紧要,并且块只是“做”某事,所以链接没有意义。
语法中的这种区别传达了关于块的评估的视觉含义,以及您是否应该关心其返回值。
例如,这里块的返回值应用于每个项目:
items.map { |i| i.upcase }
但是,这里没有使用块的返回值。它在程序上运行,并与它一起产生副作用:
items.each do |item|
puts item
end
语义样式的另一个好处是,您不需要更改大括号来执行/结束只是因为已将一行添加到块中。
作为观察,巧合的功能块通常是单行的,并且程序块(例如,配置)是多行的。因此,遵循Weirich风格最终看起来与Rails风格几乎相同。
多年来我一直使用Weirich风格,但只是远离它,总是使用牙箍。我不记得曾经使用过块样式的信息,而且定义有点模糊。例如:
date = Timecop.freeze(1.year.ago) { format_date(Time.now) }
customer = Timecop.freeze(1.year.ago) { create(:customer) }
这些是前瞻性的还是功能性的?
在我看来,行计数是没用的。我知道,是否有1行或更多行,为什么我应该更改样式只是因为我添加或删除了行?
以上是关于使用do block vs braces {}的主要内容,如果未能解决你的问题,请参考以下文章
当返回语句时,逗号运算符,braced-init-list和std :: unique_ptr合并在一起