[comp.lang.perl] Bug or misunderstanding?

alfie%cs.warwick.ac.uk@nsfnet-relay.ac.uk (Nick Holloway) (02/27/90)

[I am sending this via mailing list, since news is a bit dodgy here]

I am trying to split an array into two arrays. One will contain any
elements that match any pattern in a pattern array, and the other
contains all others. Here is the section of code that is causing me
grief:

	@text = ( "Hello", "Joe", "Schmoe", "Gordon" );
	@pat = ( "e", "o" );
	text: for $text ( @text ) {
	    for $pat ( @pat ) {
		if ( $text =~ /$pat/i ) {
		    print "Match: $pat: $text\n";
		    next text;
		}
	    }
	    print "NoMatch: $text\n";
	}

I know that I am using the same name in different contexts, but arrays,
constants and labels should have a separate namespace (right?).

The problem seems to be with the "next text;" line. I need that there,
since otherwise elements may be matched with more than one pattern. I
can't use a "last;" just to skip the rest of the patterns, coz I need
to keep elements that do not match. However, the above code does not
work as expected. Here is the sample output

	Match: e: Hello
	Match: o: Joe
	NoMatch: Schmoe
	Match: o: Gordon

Note that "Joe" did not match on the "e" but on the "o", and "Schmoe" didn't
match at all!

Have I misunderstood something vital? This is my first attempt to use
labelled "next/last"s, and it is possible I have missed something in
the manual. If so, I am open to suggestions of better ways of doing
it.  Perhaps if I spell Randal's name wrong, he'll give me a one liner :-) 
At the moment, I am inclined to think it is a bug.

BTW. This shows up in perl 3.0 patchlevel 8 on a Sun4.
--
JANET       : alfie@uk.ac.warwick.cs               |  `O O'  | Nick Holloway
BITNET/EARN : alfie%uk.ac.warwick.cs@ukacrl        | // ^ \\ | Comp Sci Dept
INTERNET    : alfie%cs.warwick.ac.uk@nsfnet-relay.ac.uk      | Uni of Warwick
UUCP        : ..!mcsun!ukc!warwick!alfie, alfie@warwick.UUCP | Coventry, UK.

merlyn@iwarp.intel.com (Randal Schwartz) (02/28/90)

In article <2860@uvaarpa.virginia.edu>, alfie%cs (Nick Holloway) writes:
| [I am sending this via mailing list, since news is a bit dodgy here]
| 
| I am trying to split an array into two arrays. One will contain any
| elements that match any pattern in a pattern array, and the other
| contains all others. Here is the section of code that is causing me
| grief:
| 
| 	@text = ( "Hello", "Joe", "Schmoe", "Gordon" );
| 	@pat = ( "e", "o" );
| 	text: for $text ( @text ) {
| 	    for $pat ( @pat ) {
| 		if ( $text =~ /$pat/i ) {
| 		    print "Match: $pat: $text\n";
| 		    next text;
| 		}
| 	    }
| 	    print "NoMatch: $text\n";
| 	}
| 
| I know that I am using the same name in different contexts, but arrays,
| constants and labels should have a separate namespace (right?).
| 
| The problem seems to be with the "next text;" line. I need that there,
| since otherwise elements may be matched with more than one pattern. I
| can't use a "last;" just to skip the rest of the patterns, coz I need
| to keep elements that do not match. However, the above code does not
| work as expected. Here is the sample output
| 
| 	Match: e: Hello
| 	Match: o: Joe
| 	NoMatch: Schmoe
| 	Match: o: Gordon
| 
| Note that "Joe" did not match on the "e" but on the "o", and "Schmoe" didn't
| match at all!
| 
| Have I misunderstood something vital? This is my first attempt to use
| labelled "next/last"s, and it is possible I have missed something in
| the manual. If so, I am open to suggestions of better ways of doing
| it.  Perhaps if I spell Randal's name wrong, he'll give me a one liner :-) 
| At the moment, I am inclined to think it is a bug.

Well, here's the one-liner (but you spelled my name right):

@hasit = grep(/e/i,@text); @neverhaditneverwill = grep(!/e/i, @text);

I got the same results as you running your code on a Sun3 rev 6.
Your code should have worked (methinks).  Larry?

As a workaround (read: kludge),	 I got the right results with the
following putziness:

@text = ( "Hello", "Joe", "Schmoe", "Gordon" );
@pat = ( "e", "o" );
for $text ( @text ) {
	inner: {
		for $pat ( @pat ) {
			if ( $text =~ /$pat/i ) {
				print "Match: $pat: $text\n";
				last inner;
			}
		}
		print "NoMatch: $text\n";
	}
}

I use labled blocks quite a bit.  Like, for a "loop...end loop"
sorta construct, instead of the C-like idiom of:

	LOOP: while (1) {
		...
		...
		last LOOP if some_condition;
		...
		...
	}

I use:

	LOOP: {
		...
		...
		last LOOP if some_condition;
		...
		...
		redo LOOP;
	}

I guess I don't like to see that funky '1' there when it isn't being
evaluated.  No, I haven't looked at the code to see if it actually got
optimized away.

for (split(/(.)/,"Just another Perl hacker,")) {print if $_;}
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/28/90)

In article <1990Feb27.174836.21449@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes:
: In article <2860@uvaarpa.virginia.edu>, alfie%cs (Nick Holloway) writes:
: | I am trying to split an array into two arrays. One will contain any
: | elements that match any pattern in a pattern array, and the other
: | contains all others. Here is the section of code that is causing me
: | grief:
: | 
: | 	@text = ( "Hello", "Joe", "Schmoe", "Gordon" );
: | 	@pat = ( "e", "o" );
: | 	text: for $text ( @text ) {
: | 	    for $pat ( @pat ) {
: | 		if ( $text =~ /$pat/i ) {
: | 		    print "Match: $pat: $text\n";
: | 		    next text;
: | 		}
: | 	    }
: | 	    print "NoMatch: $text\n";
: | 	}
: | 
: | I know that I am using the same name in different contexts, but arrays,
: | constants and labels should have a separate namespace (right?).

That's no problem.

: | 
: | The problem seems to be with the "next text;" line. I need that there,
: | since otherwise elements may be matched with more than one pattern. I
: | can't use a "last;" just to skip the rest of the patterns, coz I need
: | to keep elements that do not match. However, the above code does not
: | work as expected. Here is the sample output
: | 
: | 	Match: e: Hello
: | 	Match: o: Joe
: | 	NoMatch: Schmoe
: | 	Match: o: Gordon
: | 
: | Note that "Joe" did not match on the "e" but on the "o", and "Schmoe" didn't
: | match at all!
: | 
: | Have I misunderstood something vital? This is my first attempt to use
: | labelled "next/last"s, and it is possible I have missed something in
: | the manual. If so, I am open to suggestions of better ways of doing
: | it.  Perhaps if I spell Randal's name wrong, he'll give me a one liner :-) 
: | At the moment, I am inclined to think it is a bug.

It WAS a bug till today.  It wouldn't have been a bug in a language with
decent exception handlers...

: Well, here's the one-liner (but you spelled my name right):
: 
: @hasit = grep(/e/i,@text); @neverhaditneverwill = grep(!/e/i, @text);

You meant

@hasit = grep(/[eo]/i,@text); @neverhaditneverwill = grep(!/[eo]/i, @text);

: I use labled blocks quite a bit.  Like, for a "loop...end loop"
: sorta construct, instead of the C-like idiom of:
: 
: 	LOOP: while (1) {
: 		...
: 		...
: 		last LOOP if some_condition;
: 		...
: 		...
: 	}
: 
: I use:
: 
: 	LOOP: {
: 		...
: 		...
: 		last LOOP if some_condition;
: 		...
: 		...
: 		redo LOOP;
: 	}
: 
: I guess I don't like to see that funky '1' there when it isn't being
: evaluated.  No, I haven't looked at the code to see if it actually got
: optimized away.

"while (1)" does get optimized, basically.  And it'll be faster than your
version, because it doesn't have to do a longjmp() at the end of every loop.

Though I prefer "for (;;)" myself.

Turns out you can just say "while ()" also, since that's what the middle
term of the for loop translates into.

It all comes out to the same thing internally.  Except the redo version.

: for (split(/(.)/,"Just another Perl hacker,")) {print if $_;}

Interestingly, I had broken this here.  It told me "split loop".  So I
unbroke it.

Jest, the nether Perl heckler,
Larry

emv@math.lsa.umich.edu (Edward Vielmetti) (02/28/90)

   : for (split(/(.)/,"Just another Perl hacker,")) {print if $_;}

   Interestingly, I had broken this here.  It told me "split loop".  So I
   unbroke it.

   Jest, the nether Perl heckler,
   Larry

Uh huh.  So any version of perl has to pass the "Just another Perl hacker,"
test, with all of Randal's one-liners generating the same output.  
(Does anyone have the complete collection to this point?  It should
be interesting study...)

--Ed

merlyn@iwarp.intel.com (Randal Schwartz) (02/28/90)

In article <7202@jpl-devvax.JPL.NASA.GOV>, lwall@jpl-devvax (Larry Wall) writes:
| : for (split(/(.)/,"Just another Perl hacker,")) {print if $_;}
| 
| Interestingly, I had broken this here.  It told me "split loop".  So I
| unbroke it.

What??? You actually look at my signatures?  And use them for testing?
In that case, we oughta have them all in the .../t directory and make
sure that "Just another Perl hacker," gets printed 89 zillion times
for all future releases!

mkdir("/tmp/$$",0777); chdir "/tmp/$$";
grep(open(X,">$_"),"1Just","2another","3Perl","4hacker,");
print join(" ",grep(s/^.//,<*>)); chdir ".."; system "rm -rf $$";
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/

merlyn@iwarp.intel.com (Randal Schwartz) (02/28/90)

In article <EMV.90Feb27183449@duby.math.lsa.umich.edu>, emv@math (Edward Vielmetti) writes:
| Uh huh.  So any version of perl has to pass the "Just another Perl hacker,"
| test, with all of Randal's one-liners generating the same output.  

Deja vu!

| (Does anyone have the complete collection to this point?  It should
| be interesting study...)

Larry has been archiving comp.lang.perl, and the mailing list before
it.  *I've* only been saving what *other* people have written.  And
what do you mean, "interesting study"?  I can see it now... "the
warped mind of Randal vs. Perl... a case study in progressive
degeneracy". :-)

$_ = <<END; s/../pack('C',hex($&))/ge; print;
4a75737420616e6f74686572205065726c206861636b65722c
END
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/