From: sabbyxtabby@... (Sabby and Tabby) Date: 2004-02-03T12:45:04+09:00 Subject: Re: Save the flip/flop op! This one short-circuits, evaluating the left operand when the flip-flop is false and the right operand when true: class FlipFlop attr_accessor :flip @@FF = Hash.new {|h,k| h[k] = FlipFlop.new} def FlipFlop.[](id) @@FF[id] end def initialize @flip = Proc.new if block_given? @in_range = false @num = 0 end def flop(like=:awk) if @in_range @in_range = ! yield else @in_range = @flip[] or return @in_range = ! yield if like == :awk end @num = String === @num ? 1 : @in_range ? @num + 1 : "#{@num + 1}E0" end def flop!(&b) flop(:sed, &b) end end module Kernel def flip(id=caller[0]) FlipFlop[id].flip = Proc.new FlipFlop[id] end end puts ".. and ..." a = (1..10).map {|i| i==3 .. (i+=0.5 and i==6.5) ? i : -i} b = (1..10).map {|i| i==3 ... (i+=0.5 and i==6.5) ? i : -i} p a, b puts "#flip#flop and #flip#flop!" a = (1..10).map {|i| flip {i==3}.flop {i+=0.5 and i==6.5} ? i : -i} b = (1..10).map {|i| flip {i==3}.flop! {i+=0.5 and i==6.5} ? i : -i} p a, b Internal state is maintained using #caller info, so an explicit :label is required if there is more one #flip#flop per line: a = (1..10).select do |i| flip(:x) {i==3}.flop {i==7} and flip(:y) {i==5}.flop {i==9} end Maybe useful, maybe not, but returns a sequence number, like Perl: ('a'..'z').each {|x| i = flip {x=~/[ep]/}.flop {x=~/[iw]/} puts "#{x}: #{i.inspect}" } Outputs: a: nil b: nil c: nil d: nil e: 1 f: 2 g: 3 h: 4 i: "5E0" j: nil k: nil l: nil m: nil n: nil o: nil p: 1 q: 2 r: 3 s: 4 t: 5 u: 6 v: 7 w: "8E0" x: nil y: nil z: nil