[英]Why does a Flip-Flop operator include the second condition?
以下代码使用触发器操作符。
(1..10).each {|x| print "#{x}," if x==3..x==5 }
为什么结果3,4,5
?
我认为它应该是3,4
。
正如教程中所提到的,当x == 3
时,该表达式变为true,并且在x == 5
之前一直为真。 如果评价为假,怎么会打印'5'? 有人可以请我澄清一下吗?
“Ruby编程语言”的重要环节是:
当..和...运算符用于条件(如if语句)或循环(例如while循环)时(有关条件和循环的更多信息,请参阅第5章),它们不会创建Range对象。 相反,他们创建了一种特殊的布尔表达式,称为触发器。 触发器表达式的计算结果为true或false,就像比较和等式表达式一样。 然而,关于触发器表达的非常不寻常的事情是它的值取决于先前评估的值。 这意味着触发器表达式具有与之相关的状态; 它必须记住以前评估的信息。 因为它有状态,你会期望触发器成为某种对象。 但它不是 - 它是一个Ruby表达式,并且Ruby解释器在其表达式的内部解析表示中存储它所需的状态(只是一个布尔值)。
考虑到这一背景,请考虑以下代码中的触发器。 请注意,代码中的第一个..创建一个Range对象。 第二个创建触发器表达式:
(1..10).each {|x| print x if x==3..x==5 }
触发器由两个布尔表达式组成,它们在条件或循环的上下文中与..运算符连接。 触发器表达式为false,除非并且直到左手表达式的计算结果为真。 一旦表达式成为现实,表达式就会“翻转”为持久的真实状态。 它保持在该状态,随后的评估将返回true,直到右侧表达式求值为true。 当发生这种情况时,触发器“翻转”回到持久的错误状态。 对表达式的后续计算返回false,直到左手表达式再次变为true。 在代码示例中,触发器被重复计算,x的值从1到10.它从假状态开始,当x是1和2时评估为假。当x == 3时,翻转 - 翻转翻转为true并返回true。 当x为4和5时,它继续返回true。然而,当x == 5时,触发器将翻转为false,并对x的剩余值返回false。 结果是此代码打印345。
..
或者触发器继承自Perl,它从AWK获得并在* nix中获得。 它功能非常强大,但在你的特定用途中它是相当模糊的,并不是你想要的逻辑的好选择,特别是在Ruby中。 而是使用:
(1..10).each {|x| puts x if (3..5) === x }
哪个输出:
3
4
5
也就是说,当您需要从文件中提取一系列行时,它非常强大:
File.foreach('/usr/share/dict/propernames') { |li| puts li if ($. == 5 .. $. == 7) }
哪个输出:
Agatha
Ahmed
Ahmet
Perl只使用当前读取行(AKA $.
)的行号允许更简洁的表达式,但Ruby不支持它。
还可以选择使用正则表达式,其行为与之前的比较相似:
File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^Wa/] .. li[/^We/]) }
哪个输出:
Wade
Walt
Walter
Warren
Wayne
Wendell
因为正则表达式工作,所以可以创建一个复杂的模式来根据匹配从文件中检索行。 作为第一个,然后是第二个模式触发器,捕获线。 如果,在文件的后面,另一行触发第一个模式,则再次发生捕获,直到第二个模式匹配。 它非常强大:
File.foreach('/usr/share/dict/propernames') { |li| puts li if (
li[/^Am/] .. li[/^An/] or
li[/^Wa/] .. li[/^We/]
)
}
哪个输出:
Amanda
Amarth
Amedeo
Ami
Amigo
Amir
Amos
Amy
Anatole
Wade
Walt
Walter
Warren
Wayne
Wendell
或者,对于我们模糊代码的朋友说:
File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^(?:Am|Wa)/] .. li[/^(?:An|We)/]) }
我找到一段代码来说明触发器是如何工作的(就在这段代码出现的同一本书中,希望它能帮助那些像我一样有问题的人)
$state = false # Global storage for flip-flop state
def flipflop(x) # Test value of x against flip-flop
if !$state # If saved state is false
result = (x == 3) # Result is value of lefthand operand
if result # If that result is true
$state = !(x == 5) # Then saved state is not of the righthand operand
end
result # Return result
else # Otherwise, if saved state is true
$state = !(x == 5) # Then save the inverse of the righthand operand
true # And return true without testing lefthand
end
end
您在寻找专属系列吗? 你可以使用三个点和cover?
方法。
(1..10).each { |x| print "#{x}," if (3...5).cover?(x) }
在你的例子中它打印3,4,5的原因是因为它表示如果x在3到5的范围内打印它。
为了澄清@MurifoX的注释,触发器在x==5
之前是真的,因此当x==5
时是真的,但是每次在此之后计算表达式时它都是假的。 因此,你仍然看到5被打印。
触发器表达式的计算结果为true或false,就像比较和等式表达式一样。 然而,关于触发器表达的非常不寻常的事情是它的值取决于先前评估的值。 这意味着触发器表达式具有与之相关的状态; 它必须记住以前评估的信息。 因为它有状态,你会期望触发器成为某种对象。 但它不是 - 它是一个Ruby表达式,并且Ruby解释器在其表达式的内部解析表示中存储它所需的状态(只是一个布尔值)。 考虑到这一背景,请考虑以下代码中的触发器。 请注意,代码中的第一个“..”创建一个Range对象。 第二个创建触发器表达式:
(1..10).each {|x| print x if x==3..x==5 }
触发器由两个布尔表达式组成,它们在条件或循环的上下文中与..运算符连接。 触发器表达式为false,除非并且直到左手表达式的计算结果为真。 一旦该表达式变为真,表达式“翻转”为持久的真实状态。 它保持在该状态,随后的评估将返回true,直到右侧表达式求值为true。 当发生这种情况时,触发器“翻转”回到持久的错误状态。 对表达式的后续计算返回false,直到左手表达式再次变为true。 在代码示例中,触发器被重复评估,x的值从1到10.它以假状态开始,并且当x是1和2时评估为假。 当x == 3时,触发器翻转为真并返回true。 当x为4和5时,它继续返回true。 然而,当x == 5时,触发器将翻转为假,并对x的剩余值返回false。 结果是此代码打印345。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.