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

I thought … meant inclusive and … meant ‘not including matching lines’.

Why do these snippets both do exactly the same thing:

irb(main):032:0> File.open(‘filename’) {|f|
irb(main):033:1* f.each_line{|l|
irb(main):034:2* puts l if l=~/BEGIN/ … l=~/END/
irb(main):035:2> }
irb(main):036:1> }

Output:
10 BEGIN PATTERN
eleven
12
thirteen
14 END PATTERN

irb(main):026:0> File.open(‘filename’) {|f|
irb(main):027:1* f.each_line{|l|
irb(main):028:2* puts l if l=~/BEGIN/ … l=~/END/
irb(main):029:2> }
irb(main):030:1> }

Output:
10 BEGIN PATTERN
eleven
12
thirteen
14 END PATTERN

Both … and … produced the same output. I would have expected the
output of the second snippet to be:

eleven
12
thirteen

???

Phil

When constructing ranges of values (such as Fixnums), … excludes the
end, while … includes it.

So:

(1…10).each { |i| puts i }

prints 1 - 10, while:

(1…10).each { |i| puts i }

prints 1 - 9.

As far as I know, … and … are identical in flip-flops (which I
thought was in the Pickaxe, but I
can’t find it right now, so maybe I just read it here a while ago).

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops
in the future (in Rite, maybe?), so you may want to look into other ways
of doing stuff (if you’re
worried about it running in 2.0 and beyond, that is).

  • Dan

Dan Doel wrote:

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops

Which is a darn shame.

When constructing ranges of values (such as Fixnums), … excludes the
end, while … includes it.

So:

(1…10).each { |i| puts i }

prints 1 - 10, while:

(1…10).each { |i| puts i }

prints 1 - 9.

As far as I know, … and … are identical in flip-flops (which I
thought was in the Pickaxe, but I
can’t find it right now, so maybe I just read it here a while ago).

identical as in there is no difference in behavior between them?

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops
in the future (in Rite, maybe?), so you may want to look into other ways
of doing stuff (if you’re
worried about it running in 2.0 and beyond, that is).

taking out flip-flops?! But they seem so useful in certain situations.
Why get rid of them? (Matz?)

Phil

···

In article 401B6792.10204@po.cwru.edu, Dan Doel djd15@po.cwru.edu wrote:

previous.sub(/a darn shame/, ‘wonderful’)

This rubyist will be much happier when the flip-flop is buried.

Nathaniel

<:((><

···

On Jan 31, 2004, at 09:38, Michael campbell wrote:

Dan Doel wrote:

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops

Which is a darn shame.

Phil Tomson wrote:

identical as in there is no difference in behavior between them?

Yes, that’s what I meant.

As for all the stuff about what to replace it with and such (not just
the parent post, but many others)…

Some of the examples given can be done almost as easily without flip
flops, as long as you don’t insist on doing things within a loop.
I realize this isn’t the general case, but sometimes they turn out
that way, for instance:

The Perl code that needs to be duplicated in Ruby is:
while (<>) {
$in_header = 1 … /^$/;
$in_body = /^$/ … eof();
}

This can be done by something like this (borrowing from your modified code):

File.open(“filename”) do |f|
str = f.readlines
m = /\n\n/.match str
in_header = m.pre_match
in_body = m.post_match
end

This is as short as your flip flop code, and in fact, I can eliminate 1
line.

I also cooked up a little magic in an attempt to reproduce flip flops on my
own. It, of course, doesn’t work as well as real flip flops. Here’s my code:

module Kernel
def between(a, b, &blk)
within = false
proc do |l|
within = true if a === l
blk.call l if within
within = false if b === l
end
end
end

With this, the following two pieces of code produce identical output:

lines.each { |l|
puts l if l=~/BEGIN/ … l=~/END/
}

lines.each &between(/BEGIN/, /END/ { |l|
puts l
}

Further, you can technically chain together #between calls to make
nested flipflops, but it looks very ugly. It’s not as general as
flip flops, nested or otherwise, either, so I’ll let this stew for
a while and see if I can come up with any hideous code that makes
homebrew flip flops look nice.

As for the devil’s advocate talking about Unix idioms as methods,
I’d point out that I can define my own #grep and use it, so you’d
have to look it up anyway. I cannot define my own Ruby syntax based
on other languages. Just a little devil’s advocate back at you. :slight_smile:

I, for one, don’t have a strong opinion about whether flip flops
should be in the language. From the perl code posted, it looks like
that’s where it’s taken from. Matz is also considering taking out
some other perlisms, I believe (like certain $ variables), so
maybe this is something else he took from perl that he wishes he
didn’t. However, I’d note that taking this out isn’t a catastrophe.
Most languages don’t have such an idiom, and they do fine. And,
maybe we can even figure out something to replace it that isn’t
too bad from either side’s perspective, given that Ruby is quite
able to be modified by itself for things like this.

Sorry for the long post.

  • Dan

Nathaniel Talbott wrote:

···

On Jan 31, 2004, at 09:38, Michael campbell wrote:

Dan Doel wrote:

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops

Which is a darn shame.

previous.sub(/a darn shame/, ‘wonderful’)

This rubyist will be much happier when the flip-flop is buried.

Why? If you didn’t like it, why would you use it?

In article 45F0D15E-5404-11D8-83F8-000A95CD7A8E@talbott.ws,

···

Nathaniel Talbott nathaniel@talbott.ws wrote:

On Jan 31, 2004, at 09:38, Michael campbell wrote:

Dan Doel wrote:

However, regarding this and your last mail, I believe Matz is
considering taking out flip-flops

Which is a darn shame.

previous.sub(/a darn shame/, ‘wonderful’)

This rubyist will be much happier when the flip-flop is buried.

Why? Care to elaborate? If you don’t like them, you don’t have to use
them, right? But if you do like the feature it saves a good bit of
coding.

Phil

Dan Doel wrote:

I, for one, don’t have a strong opinion about whether flip flops
should be in the language. From the perl code posted, it looks like
that’s where it’s taken from. Matz is also considering taking out
some other perlisms, I believe (like certain $ variables), so
maybe this is something else he took from perl that he wishes he
didn’t.

I can’t speak for Matz, but my impression is that the perlisms
belonged in there, but are now wearing thin. Ruby is approxmiately
ten years old, and there are many things that are acceptable for
five-year-olds but not ten-year-olds. :slight_smile:

As for the swearing variables, I have never liked the idea of
changing the behavior of a piece of code or a library function by
altering the value of a global. After all, why are global variables
usually considered bad?

As for the flipflop issue, I favor a solution that makes sense in
terms of normal Ruby syntax and semantics.

Given that only false and nil are false, and a range is never nil,
why should

 if x..y
    puts "yes"
 else
    puts "no"
 end

ever print “no”?

Just my opinion.

Hal

Actually there is a difference… see:

http://sean.chittenden.org/programming/ruby/programming_ruby/
language.html

Search for “Ranges in Boolean Expressions” (this was missing from the
online pickaxe at rubycentral.com - not sure why).

If someone can explain the difference in a meaningful way, I’d be
grateful… I have enough trouble with the flip-flop as it is, and now
this!

Nathaniel

<:((><

···

On Jan 31, 2004, at 16:51, Dan Doel wrote:

Phil Tomson wrote:

identical as in there is no difference in behavior between them?

Yes, that’s what I meant.

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 that I have to look up every time, it
makes it much harder to grok what’s going on. Since I learn most
libraries by reading their code (and I often do that even when they
have top-notch docs - I’m just that kind of guy), opaque language
constructs are particularly biting.

Secondly, and really more importantly, is the issue of aesthetics.
Every bit of syntax, whether I use it or not, affects and reflects the
language as a whole. One of the things I like about Ruby the language
is that the syntax tends to explain itself. I don’t use or even see for
loops very much in Ruby code, but when I run across one, it’s pretty
obvious what’s going on. The flip-flop gives me no external clues as to
its modus operandi, and I don’t like the way affects Ruby, by making a
bit of the gem opaque, and how it reflects Ruby, when someone sees it
and goes, “WHAT IN TARNATION IS THAT THING?!?” and I have to explain
that Ruby unfortunately gained a few of the “P” language’s bad points
along with a lot of its good points.

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:

Just my $0.02,

Nathaniel

<:((><

···

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

Nathaniel Talbott wrote:

This rubyist will be much happier when the flip-flop is buried.

Why? If you didn’t like it, why would you use it?

http://sean.chittenden.org/programming/ruby/programming_ruby/
language.html

Search for “Ranges in Boolean Expressions” (this was missing from the
online pickaxe at rubycentral.com - not sure why).

If someone can explain the difference in a meaningful way, I’d be
grateful… I have enough trouble with the flip-flop as it is, and now
this!

The 2 dot form evaluates the end condition at the same time as the beginning one, so will flip to “on” then “off” if both are true. The 3 dot form does not.

Ah, I see.

Well, I can explain it.

When you use “expr1…expr2”, if expr1 and expr2 are both true for some
element,
then the expression evaluates to true for just that element. That is, it
gets turned
on, evaluates the code, and then turns it off. In other words, it’s
doing this in the
internal state:

within_range = false
collection.each do |l|
within_range = true if expr1
#do stuff
within_range = false if expr2
end

When you use 3 dots, it seems you can either turn it on or turn it off,
but not
both on an iteration (although it only talks about turning it on). So
it’s doing
something more like this:

within_range = false

collection.each do |l|
if within_range || expr1
#do stuff
end

if !within_range
   within_range = true if expr1
else
   within_range = false if expr2
end

end

Or something like that. I may not have gotten the semantics quite right.

I must say, this seems completely unrelated to … and … in the context of
ranges.

  • Dan

In article 2F46EE5C-543A-11D8-99FF-000A95CD7A8E@talbott.ws,

Phil Tomson wrote:

identical as in there is no difference in behavior between them?

Yes, that’s what I meant.

Actually there is a difference… see:

http://sean.chittenden.org/programming/ruby/programming_ruby/
language.html

Search for “Ranges in Boolean Expressions” (this was missing from the
online pickaxe at rubycentral.com - not sure why).

If someone can explain the difference in a meaningful way, I’d be
grateful… I have enough trouble with the flip-flop as it is, and now
this!

Nathaniel

Thanks for the reference. I thought I’d seen that state diagram
somewhere. It wasn’t in the online version I was checking.

The best way to illustrate the difference is to use an example. Given the
file ‘file’:

nine
10 BEGIN skdadk END
eleven
12
thirteen
14 END PATTERN
fifteen
---------END OF FILE-------------

And given the script:

File.foreach(“filename”){|l|
if l=~/BEGIN/ … l=~/END/
puts l
end
}

The output will be:

10 BEGIN skdadk END

changing the … to … , the output will be:

10 BEGIN skdadk END
eleven
12
thirteen
14 END PATTERN

I think this is different behavior from Perl’s version of the …
flip/flop, but I’ld have to check.

Phil

···

Nathaniel Talbott nathaniel@talbott.ws wrote:

On Jan 31, 2004, at 16:51, Dan Doel wrote:

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.

, 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”?

In article E15487A8-540F-11D8-83F8-000A95CD7A8E@talbott.ws,

Nathaniel Talbott wrote:

This rubyist will be much happier when the flip-flop is buried.

Why? If you didn’t like it, why would you use it?

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 that I have to look up every time, it
makes it much harder to grok what’s going on. Since I learn most
libraries by reading their code (and I often do that even when they
have top-notch docs - I’m just that kind of guy), opaque language
constructs are particularly biting.

Secondly, and really more importantly, is the issue of aesthetics.
Every bit of syntax, whether I use it or not, affects and reflects the
language as a whole. One of the things I like about Ruby the language
is that the syntax tends to explain itself. I don’t use or even see for
loops very much in Ruby code, but when I run across one, it’s pretty
obvious what’s going on. The flip-flop gives me no external clues as to
its modus operandi, and I don’t like the way affects Ruby, by making a
bit of the gem opaque, and how it reflects Ruby, when someone sees it
and goes, “WHAT IN TARNATION IS THAT THING?!?” and I have to explain
that Ruby unfortunately gained a few of the “P” language’s bad points
along with a lot of its good points.

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? It seems to me
that it would take several lines of code to replace the following
functionality:

f.each_line {|l|
if l=~/BEGIN/ … l=~/END/
#do something in this range of lines
end
}

If you know the meaning of what ‘…’ is doing here, it seems quite clear.
It’s also clear to anyone coming from Perl to Ruby as to what is
going on here. Without the flip/flop op that code code has to become
something like:

#untested
begin_state = false
f.each_line {|l|
if l=~/BEGIN/
begin_state = true
elsif l=~/END/
begin_state = false
end
if begin_state == true
#do something in this range of lines
end
}

I’ve got to introduce a state variable and more conditionals and my one
line has grown into 5. Add another flip/flop operator to your parsing
code and you add another state variable and a bunch more lines. It’s not
uncommon to use several of these when parsing.

Save the flip/flop!

Phil

···

Nathaniel Talbott nathaniel@talbott.ws wrote:

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

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:

Nathaniel

<:((><

···

On Jan 31, 2004, at 12:37, Michael campbell 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. 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?

Hal

ptkwt@aracnet.com (Phil Tomson) wrote in message news:bvgv9u2mb1@enews1.newsguy.com

And just what would you replace that functionality with? It seems to me
that it would take several lines of code to replace the following
functionality:

f.each_line {|l|
if l=~/BEGIN/ … l=~/END/
#do something in this range of lines
end
}

What an odd operator! It took me a bit of toying around to figure out
exactly what it does (I didn’t know what the scope of its state
variable was, but evidently it’s the enclosing method).

Anyway, it seems to me you could pretty easily replace this with a
simple flipflop class:

ff = FlipFlop.new
f.each_line {|l|
ff.from(l=~/BEGIN/, l=~/END/) do
#do something in this range of lines
end
}

class FlipFlop
def initialize
@in_range = false
end

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

Seems a lot clearer than a special operator. But maybe that’s just my
Smalltalker’s minimalism coming out…

Avi

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.