为什么我不能在Ruby中将花括号与`for`循环一起使用?

时间:2019-05-12 13:10:14

标签: ruby loops for-loop

Ruby Documentation说“ do/end等同于花括号”,所以为什么当我尝试执行以下操作时却没有收到任何输出:

a = [1, 2, 3]
for i in a {
  puts i
}

执行上述操作时,我没有输出(但也没有收到错误消息)。但是,当我执行以下操作时,一切应该保持不变:

a = [1, 2, 3]
for i in a do
  puts i
end
#=> 1
#=> 2 
#=> 3

我知道可以使用each语句来惯用此方法,但这不是我要的。我在这里不明白什么?

2 个答案:

答案 0 :(得分:3)

  

Ruby Documentation说“ do/end等于花括号”

不,不是。它说(粗体强调我的):

  

在这种情况下do / end等同于花括号[…]

“在这种情况下”的含义是直接在您引用的半句之前定义的:

  

do

     

end配对,可以分隔代码块

因此,“在此上下文中”此处是指 block 的上下文。

  

那为什么当我尝试执行以下操作时却没有收到任何输出信息

因为这是一个完全不同的上下文,所以再次引用链接到的文档:

  

do也可以(可选)出现在for / in语句的末尾。 (有关示例,请参见for

该句中的“也”非常清楚地表明,这是关键字do不同用法,与本节中讨论的用法无关。而且,如果您查看the documentation of for,就会发现其中没有提及允许使用花括号。

  

执行上述操作时,我没有收到任何输出(但我也没有收到任何错误消息)。

那是不对的。您的代码在语法上是无效的,因为它缺少end / for表达式结尾的in关键字,因此在第4行上出现“语法错误,输入意外终止” :

ruby -c -e 'a = [1, 2, 3]
for i in a {
  puts i
}'
# -e:4: syntax error, unexpected end-of-input

如果您添加缺少的end,则会在第2行获得in `<main>': undefined method `a' for main:Object (NoMethodError)

ruby -e 'a = [1, 2, 3]
for i in a {
  puts i
}
end'
# -e:2:in `<main>': undefined method `a' for main:Object (NoMethodError)

同样,这是可以预期的,因为花括号分隔了一个代码块,所以

a {
  puts i
}

被解释为传递给a的代码块,并且由于变量无法接收参数,因此a仅方法可以为方法。因此,Ruby正确地抱怨没有找到名为a的方法。

for / in循环中,有三种方法可以从循环主体表达式中分隔出迭代器表达式(对于whileuntil循环也是如此,实际上):

  1. 表达式分隔符。表达式分隔符可以是

    1. 分号;
    2. 换行符
  2. 关键字do

因此,以下所有内容均对您的代码有效:

# non-idiomatic
for i in a; puts i end

# non-idiomatic
for i in a
puts i end

# the same but with idiomatic indentation and whitespace
for i in a
  puts i
end

# idiomatic
for i in a do puts i end

# redundant, non-idiomatic
for i in a do
  puts i
end

请注意,当我在上面说“惯用语”时,这是相对的,因为实际上for / in循环作为整体 完全是不惯用的,而您宁愿这样做:

a.each do |i|
  puts i
end

或者也许

a.each(&method(:puts))

通常最好不要混合使用I / O和数据转换,因此另一种惯用的解决方案是先将数据转换为所需的输出,然后输出,如下所示:

puts a.join("\n")

除了Kernel#puts已经对Array参数进行特殊处理并将每个元素打印在自己的行上(如IO#puts所述),因此 real 是正确的代码的惯用解决方案将是:

puts a

答案 1 :(得分:0)

在这里查看文档:{​​{3}} 它指出:

  

就像一段时间,直到那样,do是可选的。 for循环类似于   使用每个,但不会创建新的变量范围

还有

  

for循环在现代红宝石程序中很少使用。

因此,请减少使用For loop的Pythonic :)

a.each { |a| puts a }