今天看 Matz 的《Ruby编程指南》,遇到一个被称为「flip-flop」的奇特表达式:
在一个由条件式或循环所构成的上下文中,一个 flip-flop 由两个通过
..
操作符相连的布尔表达式构成。除非其左侧表达式为 true,否则一个 flip-flop 表达式就是 false,而且在左侧表达式为 true 之前,它的值都会是 false。一旦该表达式为 true ,那么它就会“flips”到一个持久的 true 状态。它会保持该状态,而且对其后续的求值也返回 true,直到其右侧表达式成为 true 为止。如果其右侧表达式为 true 了,那么该 flip-flop 就会“flops”回一个持久的false状态,对其后续的求值也返回false,直到其左侧表达式再次成为 true 为止。[...]
Flip-flop 是一个非常晦涩的 Ruby 特性,因此最好不要在你的代码中使用它。但是它们并不是 Ruby 所独有的,Ruby 从 Perl 那里继承了这个特性,而 Perl 则从 Unix 的文本处理工具 sed 和 awk 那里继承了这个特性(注4)。Flip-flop 的初衷是在一个开始模式和一个结束模式之间匹配一个文本文件的行,而且这仍然是使用它们的有效方式。下面的这个简单的 Ruby 程序展示了一个 flip-flop,它逐行地从一个文本文件中读取内容,打印出含有“TODO”的行。它会不断地打印文本行,直到读入一个空行为止:
ARGF.each do |line| # For each line of standard in or of named files print line if line=~/TODO/..line=~/^$/ # Print lines when flip-flop is true end
作者还说很难正式地描述一个 flip-flop 的精确行为
。但我不这么认为。
我想到了学习数字电路时遇到的各种触发器,于是乎,反复读了几次以上描述确定了 flip-flop 的行为到底如何后,列出了它的真值表,其中 A、B 为点两边的表达式的值(输入),Q 为其内部状态,Qn 就是 Qnext。
A B Q Qn 0 0 0 0 0 0 1 1 0 1 0 0 0 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 1 0
然后和那些触发器的真值表对照,赫然发现它就是JK 触发器——
J K Q Qn 0 0 0 0 0 0 1 1 0 1 X 0 1 0 X 1 1 1 0 1 1 1 1 0
看来 Matz 没学过数字电路 ;-)
PS: flip-flop 在电子电路中就是「触发器」的意思。。。