使用do block vs braces {}

Ala*_*orm 111 ruby coding-style

新的红宝石,穿上你的新手套.

以下两个片段之间是否有任何区别(模糊或实用)?

my_array = [:uno, :dos, :tres]
my_array.each { |item| 
    puts item
}

my_array = [:uno, :dos, :tres]
my_array.each do |item| 
    puts item
end
Run Code Online (Sandbox Code Playgroud)

我意识到括号语法允许你将块放在一行上

my_array.each { |item| puts item }
Run Code Online (Sandbox Code Playgroud)

但除此之外是否有任何令人信服的理由使用一种语法而不是另一种语法?

YOU*_*YOU 98

Ruby cookbook说括号语法的优先顺序高于do..end

请记住,括号语法的优先级高于do..end语法.考虑以下两段代码:

1.upto 3 do |x|
  puts x
end

1.upto 3 { |x| puts x }
# SyntaxError: compile error
Run Code Online (Sandbox Code Playgroud)

第二个例子仅在使用括号时有效, 1.upto(3) { |x| puts x }

  • 啊,明白了.因此,由于优先顺序,当您使用do时,您将传递块作为附加参数,但是当您使用括号时,您将块作为方法调用结果的第一个参数传递给左边. (7认同)
  • 1.send(:upto,3){| x | puts x}也有效 (2认同)
  • 我通常更喜欢简短的答案,但 bkdir 的答案要清晰得多。 (2认同)

bkd*_*dir 69

这是一个有点老问题,但我想尝试解释更多关于{}do .. end

就像以前说过的那样

括号语法的优先顺序高于do..end

但这个如何有所作为:

method1 method2 do
  puts "hi"
end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,将使用块调用method1,do..end并将method2作为参数传递给method1!这相当于method1(method2){ puts "hi" }

但如果你说

method1 method2{
  puts "hi"
}
Run Code Online (Sandbox Code Playgroud)

然后使用块调用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
}
Run Code Online (Sandbox Code Playgroud)

#### 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
Run Code Online (Sandbox Code Playgroud)

  • 这比选择的答案更清晰. (11认同)

nas*_*nas 39

Generally, the convention is to use {} when you are doing a small operation, for example, a method call or a comparison, etc. so this makes perfect sense:

some_collection.each { |element| puts element }
Run Code Online (Sandbox Code Playgroud)

But if you have slightly complex logic that goes to multiple lines then use do .. end like:

1.upto(10) do |x|
  add_some_num = x + rand(10)
  puts '*' * add_some_num
end
Run Code Online (Sandbox Code Playgroud)

Basically, it comes down to, if your block logic goes to multiple lines and cannot be fitted on the same line then use do .. end and if your block logic is simple and just a simple/single line of code then use {}.

  • 我同意将do/end用于多行块,但如果我将其他方法链接到块的末尾,我将使用大括号.从文体上来说,我喜欢{...}.method().method()over ... end.method().方法,但这可能只是我. (6认同)

And*_*Vit 5

在Ruby中,选择do endvs. { }for块有两种常见的样式:

第一种也是非常常见的样式已由Ruby on Rails普及,它基于单行还是多行的简单规则:

  • { }对单行块使用大括号
  • 使用do end多行块

这是有道理的,因为do / end在单行代码中读取效果很差,但是对于多行代码块,将结束}符挂在自己的行上与end红宝石中使用的其他所有内容(例如模块,类和方法定义(def等)不一致。)和控制结构(ifwhilecase等)

第二种较少见的样式是语义的,即已故的红宝石学家Jim Weirich提出的“ Weirich Braces ”。

  • 使用do end的程序块
  • { }对功能块使用花括号

这意味着当评估该块的返回值时,它应该是可链接的,并且花{}括号对于方法链接更有意义。

另一方面,当评估该块的副作用时,则返回值无关紧要,并且该块只是“在做”某件事,因此链接没有意义。

语法上的这种区别传达了有关块评估以及是否应该关心其返回值的视觉含义。

例如,此处将块的返回值应用于每个项目:

items.map { |i| i.upcase }
Run Code Online (Sandbox Code Playgroud)

但是,这里不使用块的返回值。它的工作程序上,和与它的副作用:

items.each do |item|
  puts item
end
Run Code Online (Sandbox Code Playgroud)

语义样式的另一个好处是,您无需更改大括号即可执行/结束操作,因为仅在行中添加了一行。

作为观察,巧合的功能块通常是单线的,而过程块(例如config)是多行的。因此,遵循Weirich风格最终看起来与Rails风格几乎相同。