No difference between .. and ... flip/flop operators?

ptkwt@aracnet.com (Phil Tomson) wrote:

Seems to work and be nestable, as in the usage here:

ff = FlipFlop.new
ff2= FlipFlop.new
f = File.open(‘filename’)
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
#inside the BEGIN … END block
ff2.from(l=~/def/,l=~/end/) do
#inside def … end block
puts l
end
end
}

But it’s more cumbersome having to predeclare all the FlipFlops.

Now that raises an interesting point. Say you had this input:

···

BEGIN
def baz
#oops, syntax error
END

BEGIN
#we shouldn’t see this line
END

Your code above would break with it (at least, wouldn’t produce what I
think most people would expect it to). So would the builtin flipflop
syntax. However, it’s easy to solve with a slight modification to the
FlipFlop class:

class FlipFlop
def initialize
@in_range = false
end

def from(start_cond, end_cond)
if start_cond
@in_range = true
@nested = FlipFlop.new
end
yield @nested if @in_range
@in_range = false if end_cond
end
end

ff = FlipFlop.new
f = File.open(‘test’)
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
>nested>
nested.from(l=~/def/,l=~/end/) do
#inside def … end block
puts l
end
end
}

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:

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

···

a: nil

In article 7434BCFA-541B-11D8-83F8-000A95CD7A8E@talbott.ws,

Nathaniel Talbott wrote:

An interesting question; I’ll try to give a coherent answer. First of
all, I have to read other people’s code, and if they use obscure,
hard-to-understand constructs

I don’t find it either of those.

that I have to look up every time

nor do I have to do that.

Point taken. But then, I know from talking to others that my opinion on
it’s clarity and my need to look it up are not isolated occurrences.

, it makes it much harder to grok what’s going on.

I understand and respect your point here, but is it not a nicer way of
saying “I find hard to grok, so it should be restricted from
everyone’s use”?

Well, I’d phrase it more as, “It’s hard for a lot of people to grok, so
we should find a better construct for it.” I don’t think the
functionality should go away, but I think it should be implemented as a
library function, not a piece of the syntax. Or, if it is syntax, that
that syntax should be more inherently self-apparent.

I’d also add the sentence, “I find it dog-ugly, so I will do everything
within my power to see that it DIES!” It’s this that really drives
me… the aesthetics of the construct just make me want to wretch. It’s
an amalgamation of several different pieces of the language that just
don’t make sense together. Oh, and it has internal state that those
various pieces don’t. It just doesn’t seem to fit in. Now if I was the
only one who had this opinion, then it should certainly stay… but
apparently matz agrees with me at some level. I’m bummed that some
people will miss it, but that’s the fun of language design - you get to
“Tick off all of the people, some of the time.” I’m glad he’s the
designer and not me :slight_smile:

Not only will it be missed, it will break a lot of code if it’s removed.
I wasn’t at RubyConf2003, so I’m not sure, but rumor has it that Matz
isn’t worried about breaking code in Ruby 2.0 (Rite), similar to what the
Perl folks are doing with Perl6.0, but it would be nice to have some sort
of mechanism where we can discuss the proposed changes that will break
things. At least in the case of Perl6 there will be a way to run legacy
code (Pony and/or a translator). Will this sort of approach be available
in Ruby 2.0? This issue needs more community discussion.

Back to the flip/flop issue:
What exactly do you propose to replace it with?

If you propose to replace this piece of syntax with a library function,
where should that function live?

Maybe in File or IO somewhere? (like so):

File.open(“filename”) {|f|
f.each_line_between(/BEGIN/,/END/) {|l|
#do something between BEGIN, END
#but what if you want to nest another one in here?
end
}

However, that doesn’t help when you’ve got several flip/flops (or
nested flip/flops) looking for
several different ranges of lines in a file like:

File.foreach(“filename”) {|f|
f.each_line {|l|
if l=~/BEGIN/ … l=~/END/
#between BEGIN and END
if l=~/def/ … l=~/end/
#between def and end inside BEGIN … END block
end
end
}
}

I don’t see any way that an ‘each_line_between’ type method would be able
to do this since it lives in File. Perhaps we should introduce an
‘each_line_between’ for simple cases, but I don’t see how it can replace
the flip/flop op for the nested case (which is commonly done).

I really hope Matz will reconsider.

Phil

···

Nathaniel Talbott nathaniel@talbott.ws wrote:

On Jan 31, 2004, at 12:37, Michael campbell wrote:

Hal Fulton wrote:

Phil Tomson wrote:

That’s why I personally would like to see it gone, and good riddance.
You, of course, are welcome to root for a pardon, but I just wanted
to make sure the other side of the aisle was represented :slight_smile:

And just what would you replace that functionality with?

Phil,

I’m with Nathaniel. Save the functionality but please KILL the
syntax.

Well, I like the syntax, because I’ve trained my brain to understand it. Would Ruby be as easy to read as it is now if all the reserved words were not in English (or in ANY known “natural” spoken language)? My point here is that anything you dont yet understand, take the time to understand it. The reason Ruby is easy now is only because you have the understanding of the context in/for which it was designed.

That said, if there were some method call which can do all of what (scalar)“…” does, then fine. The beauty of this operator is that each one has its own state (that I don’t have to burn a variable to maintain on my own), so you can nest them, have several going at once, use them completely outside of the common per-line file processing model, etc.

I THINK Hal’s solution might work outside the file-by-line context

Every solution presented thus far assumes I want to use it only for processing text files line by line, when in reality, I might need it for many other things, totally unrelated to that.

Only a perler could love it. (No offense meant.)

Playing devil’s advocate…By extension then, I propose to also put up all the unixism’s as candidates for removal too, as only people who are familiar with unix could love those too. I have to read others’ code, and I just have to grab a manual every time I see Enumerable#grep.

In article 401C0A45.3000504@hypermetrics.com,

Phil Tomson wrote:

That’s why I personally would like to see it gone, and good riddance.
You, of course, are welcome to root for a pardon, but I just wanted to
make sure the other side of the aisle was represented :slight_smile:

And just what would you replace that functionality with?

Phil,

I’m with Nathaniel. Save the functionality but please KILL the
syntax. Only a perler could love it. (No offense meant.)

Not everything in Perl was bad (No offense taken). Matz obviously got a
lot of inspiration from Perl. It’s a good thing, actually, because these
sorts of things attract a lot of Perl people looking for something better.
They find some familiar things to make them feel at home and some
different things to make it seem worthwhile to switch. Given that Perl
has the most users, this can be a good thing for Ruby to gain more users.

The flip/flop operator is a powerful piece of syntax. Just because
something isn’t well understood doesn’t mean we should just get rid of it,
it probably means it needs to be documented better for those who aren’t
familiar with Perl. To those of us who came from Perl (and I suspect
that’s a lot of us) it seems pretty natural and so far I have yet to see
any good way of replacing it. The attitude I’m hearing is that since some
peole don’t understand it, even those who do shouldn’t get to use it which
certainly doesn’t see fair to those who gain a lot of benefit from it.

Certainly I can agree, for example, that the $* vars need some synonyms in
English (and I think most of them already have them), but I also think they
should still be available for legacy sake.

I haven’t thought this through yet. But let’s do it with a
method call.

#untested
f.set_context(/BEGIN/,/END/)
f.each_line do |l|
if f.in_context
# do something with l…
else
# whatever
end
end

Comments, Phil? Nathaniel? Others?

The same question remains: is it nestable? Would I be able to do:

#untested
f.set_context(/BEGIN/,/END/)
f.each_line do |l|
if f.in_context
# do something with l…
f.set_context(/def/,/end/)
if f.in_context
#do something between def and end inside of BEGIN END block
end
else
# whatever
end
end

It doesn’t seem like it. If not, then we’ve lost a lot of functionality.

Also, I would suggest that whatever new mechanism is introduced that there
still be a way to use the old one, even if it means something like:

require “pre2.0”
#…
if line=~/BEGIN/ … line=~/END/

#…

…problem is that in this case we’re talking about some syntax being
deprecated and you can’t get that back with a require in this case AFAIK.

Phil

···

Hal Fulton hal9000@hypermetrics.com wrote:

In article 6e869a6b.0401311614.1334a5fc@posting.google.com,

I wrote:

def from(start_cond, end_cond)
@in_range = true if start_cond
yield
@in_range = false if end_cond
end

Ack. That should be “yield if @in_range”, of course.

Seems to work and be nestable, as in the usage here:

ff = FlipFlop.new
ff2= FlipFlop.new
f = File.open(‘filename’)
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
#inside the BEGIN … END block
ff2.from(l=~/def/,l=~/end/) do
#inside def … end block
puts l
end
end
}

But it’s more cumbersome having to predeclare all the FlipFlops.

Phil

···

Avi Bryant avi@beta4.com wrote:

“Hal Fulton” hal9000@hypermetrics.com schrieb im Newsbeitrag
news:401C0A45.3000504@hypermetrics.com

Phil Tomson wrote:

That’s why I personally would like to see it gone, and good riddance.
You, of course, are welcome to root for a pardon, but I just wanted to
make sure the other side of the aisle was represented :slight_smile:

And just what would you replace that functionality with?

Phil,

I’m with Nathaniel. Save the functionality but please KILL the
syntax. Only a perler could love it. (No offense meant.)

I haven’t thought this through yet. But let’s do it with a
method call.

#untested
f.set_context(/BEGIN/,/END/)
f.each_line do |l|
if f.in_context
# do something with l…
else
# whatever
end
end

Comments, Phil? Nathaniel? Others?

I wouldn’t put it into File or IO since this is too specialized
functionality. It deserves a class of it’s own:

class FlipFlop
def initialize(on, off)
@on, @off = on, off
@state = false
end

def ===(o)
if @state
@state = false if @off === o
else
@state = true if @on === o
end

@state

end
end

io=<<TEXT
foo
BEGIN
bar
BEGIN
baz
END
bar
TEXT

ff = FlipFlop.new /BEGIN/, /END/

io.each_line do |line|
line.chomp!
puts “#{ff === line}: #{line}”
end

Yields

false: foo
true: BEGIN
true: bar
true: BEGIN
true: baz
false: END
false: bar

If you want to include the last line you can do:

class FlipFlop2
def initialize(on, off)
@on, @off = on, off
@state = false
end

def ===(o)
old = @state

if @state
  @state = false if @off === o
else
  old = @state = true if @on === o
end

old

end
end

Yields:

false: foo
true: BEGIN
true: bar
true: BEGIN
true: baz
true: END
false: bar

Regards

robert

Michael campbell wrote:

Well, I like the syntax, because I’ve trained my brain to understand
it. Would Ruby be as easy to read as it is now if all the reserved
words were not in English (or in ANY known “natural” spoken language)?
My point here is that anything you dont yet understand, take the time to
understand it. The reason Ruby is easy now is only because you have the
understanding of the context in/for which it was designed.

Well, it runs counter to the rest of Ruby.

Since x…y is a range, and never evaluates to false or nil, I would
expect it always to be true.

That said, if there were some method call which can do all of what
(scalar)“…” does, then fine. The beauty of this operator is that each
one has its own state (that I don’t have to burn a variable to maintain
on my own), so you can nest them, have several going at once, use them
completely outside of the common per-line file processing model, etc.
I THINK Hal’s solution might work outside the file-by-line context

Every solution presented thus far assumes I want to use it only for
processing text files line by line, when in reality, I might need it for
many other things, totally unrelated to that.

That may be. (My solution of course was extremely half-baked.) In that
case, I’d suggest a class for that purpose. A class as general-purpose
as possible.

Only a perler could love it. (No offense meant.)

Playing devil’s advocate…By extension then, I propose to also put up
all the unixism’s as candidates for removal too, as only people who are
familiar with unix could love those too. I have to read others’ code,
and I just have to grab a manual every time I see Enumerable#grep.

I see your point, but I don’t admit the correspondence. (My turn to play
devil’s advocate.)

I didn’t mean it was ugly and obtuse because it came from Perl. Many
Perlism are easy to grasp. I’d be lost without =~ and regex literals.

I meant it was ugly and obtuse, and no one would ever think otherwise
unless he was used to Perl.

As for the Unixisms: There are some I have trouble with, and I have used
Uniux off and on since the early 80s.

I don’t know if you’re serious about “grep” or not. My only complaint
with it is the name. A unixism which has a nonintuitive name should
perhaps have an intuitive alias.

This reminds me of a BBS I was designing with a friend back in 1990 or
so. We wanted to put in a scheduling mechanism for the sysop, and we
debated how to implement it and what to call it. “Call it ‘cron’,” he
said. “We are not calling it ‘cron’,” I told him.

Hal

Phil Tomson wrote:

In article 6e869a6b.0401311614.1334a5fc@posting.google.com,

I wrote:

def from(start_cond, end_cond)
@in_range = true if start_cond
yield
@in_range = false if end_cond
end

Ack. That should be “yield if @in_range”, of course.

Seems to work and be nestable, as in the usage here:

ff = FlipFlop.new
ff2= FlipFlop.new
f = File.open(‘filename’)
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
#inside the BEGIN … END block
ff2.from(l=~/def/,l=~/end/) do
#inside def … end block
puts l
end
end
}

But it’s more cumbersome having to predeclare all the FlipFlops.

No doubt.

I haven’t had a chance to try it yet, but do either Avi’s or Nathaniel’s solutions work in the

“do_something if something…something_else”

form?

···

Avi Bryant avi@beta4.com wrote:

Nice implementation. The usage is still more verbose than the FF
operator, though. Perhaps some method to process an enumerable
object?

Untested

class FlipFlop
def process(enum)
enum.each do |o|
yield(o) if self === o
end
end
end

File.open(path) do |io|
FlipFlop.new(/BEGIN/, /END/).process(io) do |line|
puts line
end
end

Is that any good?

Gavin

···

On Sunday, February 1, 2004, 11:29:50 PM, Robert wrote:

Comments, Phil? Nathaniel? Others?

I wouldn’t put it into File or IO since this is too specialized
functionality. It deserves a class of it’s own:

class FlipFlop
def initialize(on, off)
@on, @off = on, off
@state = false
end

def ===(o)
if @state
@state = false if @off === o
else
@state = true if @on === o
end

@state

end
end

Hal Fulton wrote:

Well, it runs counter to the rest of Ruby.

I have no stance to debate that, but I’d wager that for virtually every construct in ruby 1 person considers within “the ruby way”, there would be a set of people who disagree.

Since x…y is a range, and never evaluates to false or nil, I would
expect it always to be true.

That I can concede as an inconsistency.

Every solution presented thus far assumes I want to use it only for
processing text files line by line, when in reality, I might need it
for many other things, totally unrelated to that.

That may be. (My solution of course was extremely half-baked.) In that
case, I’d suggest a class for that purpose. A class as general-purpose
as possible.

I’m open to that. As I said, so far, the people who have disliked the operator have only provided solutions to the stated examples of its use, not a general solution replacement.

I didn’t mean it was ugly and obtuse because it came from Perl. Many
Perlism are easy to grasp. I’d be lost without =~ and regex literals.

chuckle I realized what you were saying…about 30 minutes too late so apologies there. That said however, how many weeks on ruby-talk do you see pass WITHOUT a question re: regexs of some sort? What exactly about the regex syntax is within the sphere of “the spirit of ruby”, where a scalar “…” is not? Which is easier to learn? To read?

I meant it was ugly and obtuse, and no one would ever think otherwise
unless he was used to Perl.

More so than regexes?

I don’t know if you’re serious about “grep” or not. My only complaint
with it is the name. A unixism which has a nonintuitive name should
perhaps have an intuitive alias.

No, not serious in the slightest, except from a purely academic standpoint.

The point I’m attempting to make is along the lines of “whose ox is getting gored?”

“…” in a scalar context is ugly and obtuse, and yet people are willing to put up with names like “grep”, regexs, and a myriad of other things that they would accept as perfectly natural, and only because that’s their personal context and area of familiarity.

In article 401C50D5.601@yahoo.com,

···

Michael campbell michael_s_campbell@yahoo.com wrote:

Phil Tomson wrote:

In article 6e869a6b.0401311614.1334a5fc@posting.google.com,
Avi Bryant avi@beta4.com wrote:

I wrote:

def from(start_cond, end_cond)
@in_range = true if start_cond
yield
@in_range = false if end_cond
end

Ack. That should be “yield if @in_range”, of course.

Seems to work and be nestable, as in the usage here:

ff = FlipFlop.new
ff2= FlipFlop.new
f = File.open(‘filename’)
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
#inside the BEGIN … END block
ff2.from(l=~/def/,l=~/end/) do
#inside def … end block
puts l
end
end
}

But it’s more cumbersome having to predeclare all the FlipFlops.

No doubt.

I haven’t had a chance to try it yet, but do either Avi’s or Nathaniel’s
solutions work in the

“do_something if something…something_else”

form?

I haven’t tried Nathaniel’s proposed solution, but Avi’s solution takes a
block (where the action occurs), so I don’t think it would work that way.
A different method could probably be added to his FlipFLop class that
could work that way.

Phil

Hal Fulton wrote:

I meant it was ugly and obtuse, and no one would ever think otherwise
unless he was used to Perl.

Code with an invisible state always reminds me of COBOL, frankly.

···


John W. Kennedy
“But now is a new thing which is very old–
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor’s sake.”
– Charles Williams. “Judgement at Chelmsford”

“Gavin Sinclair” gsinclair@soyabean.com.au schrieb im Newsbeitrag
news:1221728269450.20040201235547@soyabean.com.au…

Comments, Phil? Nathaniel? Others?

I wouldn’t put it into File or IO since this is too specialized
functionality. It deserves a class of it’s own:

class FlipFlop
def initialize(on, off)
@on, @off = on, off
@state = false
end

def ===(o)
if @state
@state = false if @off === o
else
@state = true if @on === o
end

@state

end
end

Nice implementation.

Thanks!

The usage is still more verbose than the FF
operator, though.

Yeah, but it avoids the speciality of treating “…” and “…” differently
when they appear in an if clause.

Perhaps some method to process an enumerable
object?

Untested

class FlipFlop
def process(enum)
enum.each do |o|
yield(o) if self === o
end
end
end

File.open(path) do |io|
FlipFlop.new(/BEGIN/, /END/).process(io) do |line|
puts line
end
end

Is that any good?

It looks good. The only thing that bothers me a bit is that the iteration
is kind of “hidden”. In Ruby we typically do enum.each{|elem| do sth. with
elem}. It’s just a feeling, I can’t exactly point to why this might be bad.
The only thing that comes to my mind is that you make the whole block
dependend on the FF’s state while you might want to do something else with
the line even if the FF doesn’t match. E.g. you could be wanting to do:

io.each_line do |line|
line.chomp!

case line
when ff1
# do stuff
when ff2
# do other stuff
if ff3 === line
# nested
end
end
end

Dunno whether that is realistic.

Regards

robert
···

On Sunday, February 1, 2004, 11:29:50 PM, Robert wrote:

Here’s my stab at a replacement. My goal with it was to replace the
syntax with a library. If it doesn’t solve the general case, please
improve the tests, and I’ll do another iteration. I still wonder if
there isn’t a prettier solution to this problem in general, but this,
at least, is a start:

module BooleanRange
def flip(name, immediate=true)
raise ArgumentError, “No block” unless(block_given?)
@_flippers ||= Hash.new(false)
state = @_flippers[name]
start, finish = yield
value = state
if(state)
if(finish)
state = false
value = true
end
else
if(start)
state = !(finish && immediate)
value = true
end
end
@_flippers[name] = state
value
end

 def flip2(name, &test)
   flip(name, false, &test)
 end

end

require ‘test/unit’

class TestBooleanRanges < Test::Unit::TestCase
include BooleanRange

 def test_syntax
   assert_equal([nil, 12, nil, nil, nil, 16, 17, 18, nil, 20],
     (11..20).collect{|i| (i%4 == 0)..(i%3 == 0) ? i : nil})
   assert_equal([nil, 12, 13, 14, 15, 16, 17, 18, nil, 20],
     (11..20).collect{|i| (i%4 == 0)...(i%3 == 0) ? i : nil})
 end

 def test_extension
   assert_equal([nil, 12, nil, nil, nil, 16, 17, 18, nil, 20],
     (11..20).collect{|i| flip(:a){[i%4 == 0, i%3 == 0]} ? i : nil})
   assert_equal([nil, 12, 13, 14, 15, 16, 17, 18, nil, 20],
     (11..20).collect{|i| flip2(:b){[i%4 == 0, i%3 == 0]} ? i : nil})
 end

 def test_nesting
   a = []
   b = []
   "abc { def [ ghi jkl ] mno } pqr".split(/ /).each do |e|
     if(flip(:a){[/\{/ =~ e, /\}/ =~ e]})
       if(flip(:b){[/\[/ =~ e, /\]/ =~ e]})
         b << e unless(e =~ /\[|\]/)
       else
         a << e unless(e =~ /\{|\}/)
       end
     end
   end

   assert_equal(["def", "mno"], a)
   assert_equal(["ghi", "jkl"], b)
 end

end

It feels like to me that there’s a simple, clear and brilliant approach
hiding under this need, but I sure can’t see it at this point. If you
can, please chime in :slight_smile:

Nathaniel

<:((><

···

On Jan 31, 2004, at 17:10, Michael campbell wrote:

Hal Fulton wrote:

That may be. (My solution of course was extremely half-baked.) In that
case, I’d suggest a class for that purpose. A class as general-purpose
as possible.

I’m open to that. As I said, so far, the people who have disliked the
operator have only provided solutions to the stated examples of its
use, not a general solution replacement.

With the following code where ‘f’ is an file handle:

f.each_line{ |line|
header = 1 … $.=~$^ ? true : false
body = $^ … f.eof ? true : false }

Say body becomes true after the first \n. What is stopping header from
becoming true again on the next \n? Since it will be between 1 and the $^.
Is the flip flop op somehow storing that $^ was already reached and not to
test the condition again?

Thanks,

Zach

···

Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.576 / Virus Database: 365 - Release Date: 1/30/2004

John W. Kennedy wrote:

Hal Fulton wrote:

I meant it was ugly and obtuse, and no one would ever think otherwise
unless he was used to Perl.

Code with an invisible state always reminds me of COBOL, frankly.

Interesting, since everything in COBOL is global and there IS no visibility…

Nathaniel Talbott wrote:

It feels like to me that there’s a simple, clear and brilliant approach
hiding under this need, but I sure can’t see it at this point. If you
can, please chime in :slight_smile:

Yes, it’s the “…” operator… >=)

“Zach Dennis” zdennis@mktec.com schrieb im Newsbeitrag
news:LLENJLJKHAOFKOLPKLAFOENLCAAA.zdennis@mktec.com

With the following code where ‘f’ is an file handle:

f.each_line{ |line|
header = 1 … $.=~$^ ? true : false
body = $^ … f.eof ? true : false }

First of all, you can use FF only in if statements. Then, using “?:” to
convert boolean values to boolean values is superfluous. And btw your code
doesn’t compile for me.

Say body becomes true after the first \n. What is stopping header from
becoming true again on the next \n? Since it will be between 1 and the $^.
Is the flip flop op somehow storing that $^ was already reached and not to
test the condition again?

The behavior of the FF is like this: it’s false until the first condition
matches. If that’s the case it becomes true and stays true as long as the
second doesn’t match. After that it’s false until the first condition
matches again.

The easiest way to separate header and body of a file in mbox format is
possibly this:

io.each_line do |line|
line.chomp!

if /^From / =~ line … /^$/ =~ line
puts "Header: " + line unless line.length == 0
else
puts "Body: " + line
end
end

Of course you will have to do more processing to treat individual header
lines and deal with continued header lines. You can look into gurgitate
mail to see how it does it.

http://rubyforge.org/projects/gurgitate-mail/

Regards

robert

PERFORM THROUGH provided more than too much INvisibility. When you
combine that with GO TO that can take you anywhere and an EXIT that only
returns if there was a relevant PERFORM, the opportunities for crap code
were legion.

IIRC every compiler generated self modifying code - it was the easiest
way to handle the semantics of the language.

Ian

···

In message 401C910E.80308@yahoo.com, Michael campbell michael_s_campbell@yahoo.com writes

John W. Kennedy wrote:

Hal Fulton wrote:

I meant it was ugly and obtuse, and no one would ever think
otherwise
unless he was used to Perl.
Code with an invisible state always reminds me of COBOL, frankly.

Interesting, since everything in COBOL is global and there IS no visibility…


Ian - posting to a Newsgroup. Please remove everything to reply.