[comp.lang.perl] Regexp bug in print context?

kumon@asami.stars.flab.Fujitsu.co.jp (Kouichi Kumon) (04/13/90)

 I was amazed at the behavior of regular expression searches in
print contexts.
 The following program calls subroutine &sub twice,
and the subroutine searches the same regexp from the same string.
 But the actions are different.
 The first subroutine call succeeds, but the second doesn't.
 When regexp /(0)/ in the fifth line is changed to /(1)/ or /0/ ,
it works.

 Isn't it a bug?
--------------------------
print &sub."\n";
print &sub,"\n";
sub sub {
    $c = "xx0x1x";
    if ($c =~ /(0)/) { # Why this regexp doesn't match the pattern?
	"Ok found";
    } else {
	die " not found\n";
    }
}
--------------------------

RUNNING ENVIRONMENT
Perl patchlevel 18 under sun4/110 sunos-4.0.1, use bison -y,
compiled with cc -O2.


--
Artificial inteligence lab, Fujitsu labs.
kumon@flab.fujitsu.co.jp

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (04/14/90)

In article <KUMON.90Apr13130849@asami.stars.flab.Fujitsu.co.jp> kumon@flab.fujitsu.co.jp writes:
: 
:  I was amazed at the behavior of regular expression searches in
: print contexts.
:  The following program calls subroutine &sub twice,
: and the subroutine searches the same regexp from the same string.
:  But the actions are different.
:  The first subroutine call succeeds, but the second doesn't.
:  When regexp /(0)/ in the fifth line is changed to /(1)/ or /0/ ,
: it works.
: 
:  Isn't it a bug?
: --------------------------
: print &sub."\n";
: print &sub,"\n";
: sub sub {
:     $c = "xx0x1x";
:     if ($c =~ /(0)/) { # Why this regexp doesn't match the pattern?
: 	"Ok found";
:     } else {
: 	die " not found\n";
:     }
: }

This will be fixed in patch 19.  It's been a known problem for some
time that conditional expressions shouldn't ever be evaluated in an
array context, but it took me this long to decide how to fix it.

The way it will work is this: if a statement containing a conditional
is evaluated in an array context, the conditional is evaluated in
a scalar context, but the statement itself will return an array value.
The "last expression evaluated" rule still holds, so if no other expressions
are evaluated, the array value returned consists of a single element
containing the value of the conditional expression (which might be either
true or false, depending on the polarity of the test).

Statements containing conditionals in this sense include:

	if (conditional) {
	    expression;
	}

	unless (conditional) {
	    expression;
	}

	while (conditional) {
	    expression;
	}

	until (conditional) {
	    expression;
	}

	expression if conditional;
	expression unless conditional;
	expression while conditional;
	expression until conditional;

	conditional && expression;
	conditional || expression;

Note that an array assignment of a false value is true:

	if (@foo = do { (1,2,3) if $x; } ) {
	    print "\@foo = (@foo)\n";
	}
	else {
	    print "Never executed";
	}

This will always take the true branch, even if $x is false, since at least
1 element is always assigned to @foo.

Larry