フリップフロップのような動きをする演算子

http://d.hatena.ne.jp/hyuki/20061222#flip

面白い。また結城さんの例もシンプルで素敵だ。

でも,hyukiさんの例,入出力だけ見ると,

while (<DATA>) {
  if (/^[3-5]/) {
    print;
  }
}
# (以下略)

って書いちゃうのと変わらないところが不満。俺一人不満。

「..」な演算子が範囲を指定しつつ,0と1の状態をいったりきたりっていう,もっといい例ってなんだろう? ウクレレを弾きながらすこし考える。

フリップフロップ臭い,という意味では,立ち上がりと立ち下がり*1に注目したい。実験といえばクロック突っ込んで両方見せていた。ってことは,sinウェーブのように登ったり下ったりを繰り返す入力を試すのがやっぱそれっぽいだろう。ということで,

#!c:\perl\bin\perl
while(<DATA>) {
  if (/^3/ .. /^5/) { print; }  
#  if(/^[3-5]/){ print; }
}

__END__
111 a+
222 a+
333 a+
444 a+
555 a+
666 a+
777 a+
888 a+
888 a-
777 a-
666 a-
555 a-
444 a-
333 a-
222 a-
111 a-
111 b+
222 b+
333 b+
444 b+
555 b+
666 b+
777 b+
888 b+
888 b-
777 b-
666 b-
555 b-
444 b-
333 b-
222 b-
111 b-

というのを考えてみた。よさそうなので実行。

333 a+
444 a+
555 a+
333 a-
222 a-
111 a-
111 b+
222 b+
333 b+
444 b+
555 b+
333 b-
222 b-
111 b-

なんか想像と違う実行結果のような気がする。でも,/^[3-5]/との違いは表現できた。半分くらい満足。あと,回路をいじっていたころに「想像と違ったありがちパターン」と似ているので,たぶん直感的にはあっているんじゃないかとカンジニアリング全開。すこしわかりにくいな。でも,わかりにくいのは私が..をきちんと理解してないか,いまやたら眠いからか,その両方のせいだと思う。

いまの眠さを表現するならば,「#!c:\perl\bin\perl」と書くところを,「#!c:\bin\perl\bin」って書いちゃうくらいの眠さ。危険だ。ウクレレしまって寝よう。おやすみなさい。

追記@12/23 21:04

http://perldoc.jp/docs/perl/5.6.1/perlop.podを読んでいたらわかった。

この演算子は、フリップフロップのように 2 値安定で、 sedawk や多くのエディタでの行範囲 (コンマ) 演算子をエミュレートするものとなります。各々の ".." 演算子がそれぞれに独立して自分の真偽状態を管理します。はじめは、左被演算子が偽である間、演算全体も偽となっています。範囲演算子は、いったん左被演算子が真になると、右被演算子が真である間、真を返すようになります。右被演算子が偽になると、演算子も偽を返すようになります。

ふむ。で,

  if (/^5/ .. /^3/) {

を試して理解。なるほど。「範囲演算子」の「範囲」にとらわれると左右が対等なものに思えるけど,そうじゃないと。一個ずつ順番に試すんだね。フリップフロップの出力「X」(不定状態)を思い出したり。

しかしややこしいことするなこいつ。フリップフロップで間違えがちなパターンによく似ている。

*1:ディジタル回路用語? 立ち上がりは0から1,立ち下がりは1から0