以下代码导致参数错误:
n = 15
(n % 4 == 0)..(n % 3 == 0)
# => bad value for range (ArgumentError)
我认为是因为它评估为:
false..true
并且范围内使用了不同类型的类:TrueClass
和FalseClass
。但是,以下代码不会引发错误。这是为什么? Enumerable#collect
会抓住它吗?
(11..20).collect { |i| (i % 4 == 0)..(i % 3 == 0) ? i : nil }
# => no error
稍后添加:如果 fcn 返回15,则只评估范围的前半部分
def fcn(x)
puts x
15
end
if (fcn(1) % 4 == 0)..(fcn(2) % 3 == 0); end
# => 1
但如果我们将返回值更改为16,则输入将为
# => 1
# => 2
这很奇怪,因为在这种情况下,表达式的计算结果为
true..false
根据 sawa 的答案,这种范围无效。
然后在第一种情况下( def 的返回值15)我们只有部分范围没有结束部分?这太奇怪了:))
答案 0 :(得分:8)
在Ruby if start..finish
中是一个触发器,一种用于编写快速和模糊脚本的特殊语法。它通常用在循环中:
while input = gets
puts "Processing #{input.inspect}" if input =~ /start/ .. input =~ /end/
end
当第一个条件为真时,在每次连续执行时都认为整个条件为真,直到第二个条件的计算结果为真。您可以使用上面的脚本来获得想法。这是我的输入&输出:
foo
start
Processing "start\n"
foo
Processing "foo\n"
bar
Processing "bar\n"
end
Processing "end\n"
foo
bar
start
Processing "start\n"
请注意,如果条件未启动,Ruby不会评估完成条件,因为这样做无用。
虽然在循环之外使用它没有多大意义,但Ruby并没有限制它。
>> if nil..raise; :nothing_gonna_happen; end
=> nil
答案 1 :(得分:0)
首先,请注意以下有效和无效的文字:
true..true # => valid
false..false # => valid
true..false # => invalid
false..true # => invalid
因此,问题减少了为什么评估为false..true
和true..false
的表达式在嵌入循环条件时变为有效。根据{{3}},循环条件中的范围文字实际上并不创建范围。它具有类似于sed和awk的特殊含义。也就是说,范围开始的真实性启动循环,范围结束的真实性终止它。一些例子发现documentation。