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
语句来惯用此方法,但这不是我要的。我在这里不明白什么?
答案 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
循环中,有三种方法可以从循环主体表达式中分隔出迭代器表达式(对于while
和until
循环也是如此,实际上):
表达式分隔符。表达式分隔符可以是
;
关键字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 }