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

P

Phil Tomson

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
 
D

Dan Doel

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
 
N

Nathaniel Talbott

Which is a darn shame.

previous.sub(/a darn shame/, 'wonderful')

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


Nathaniel

<:((><
 
M

Michael campbell

Nathaniel said:
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?
 
N

Nathaniel Talbott

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 :)

Just my $0.02,


Nathaniel

<:((><
 
M

Michael campbell

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"?
 
N

Nathaniel Talbott

I don't find it either of those.



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.

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 :)


Nathaniel

<:((><
 
P

Phil Tomson

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
 
P

Phil Tomson

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
 
P

Phil Tomson

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 :)

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
 
P

Phil Tomson

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.



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 :)

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
 
H

Hal Fulton

Phil said:
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
 
P

Phil Tomson

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
 
M

Michael campbell

Hal said:
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.
 
H

Hal Fulton

Michael said:
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.
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
 
D

Dan Doel

Phil said:
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. :)

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
 
H

Hal Fulton

Dan said:
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. :)

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
 
M

Michael campbell

Hal said:
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.
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top