[comp.lang.perl] quasi-bug

vsh@etnibsd.UUCP (Steve Harris) (03/27/90)

I finally got around to upgrading to patch level 15 (from level 2) and,
while running the test suite, discovered an interesting problem:
in the test "op.stat", there is code that basically does:

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
chdir '/usr/bin';
while (<*>) {
	# increment some counters, etc.
}
# if (counter not incremented) { print error message; }
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

which kept failing on my system.  I inserted a couple print statements
and discovered the main loop was not being entered!  It looked like
file name globbing was broken!  A few more tests showed this failure
happened in the /usr/bin directory only.

Well, to make a long story short, there existed a file in /usr/bin
named 0.  That's right, the single digit zero.  So it seems that the
first time into the loop, the while test failed, i.e., the value
returned by <*> was being interpreted as a numeric, not a string
value!

Now, regardless of the fact that a file named 0 probably does not
belong in /usr/bin, is this the way the <*> construct should work???
-- 
Steve Harris - Eaton Corp. - Beverly, MA - uunet!etnibsd!vsh

tneff@bfmny0.UU.NET (Tom Neff) (03/28/90)

In article <1121@etnibsd.UUCP> vsh@etnibsd.UUCP (Steve Harris) writes:
>while (<*>) {
...
>Well, to make a long story short, there existed a file in /usr/bin
>named 0.  That's right, the single digit zero...

This problem is cool and crazy on several *levels* of cool and crazy.
It gets my vote for Best Perl Weirdness Of The Week.  :-)

now, back to rewriting login in Perl...

-- 
"We plan absentee ownership.  I'll stick to       `o'   Tom Neff
 building ships." -- George Steinbrenner, 1973    o"o   tneff@bfmny0.UU.NET

flee@shire.cs.psu.edu (Felix Lee) (03/29/90)

Perl is kinda dangerous in many ways.

I once wanted to parse multiple '-e expr' and '-f file' options the
way 'sed' does, with or without a space between the option and the
argument.  Without much thought, I wrote the following, which handles
the optional space in a single statement:
	while ($_ = shift) {
		&expression($1 || shift), next if (/^-e(.*)$/);
		&file($1 || shift), next if (/^-f(.*)$/);
		# ...
	}
Unfortunately, this doesn't work properly for '-e0', '-f0', or '0'.

If strings weren't converted to numbers in boolean contexts . . .
--
Felix Lee	flee@shire.cs.psu.edu	*!psuvax1!flee

merlyn@iwarp.intel.com (Randal Schwartz) (03/29/90)

In article <Etr4*$3@cs.psu.edu>, flee@shire (Felix Lee) writes:
| Perl is kinda dangerous in many ways.

s/kinda //; # :-)

| I once wanted to parse multiple '-e expr' and '-f file' options the
| way 'sed' does, with or without a space between the option and the
| argument.  Without much thought, I wrote the following, which handles
| the optional space in a single statement:
| 	while ($_ = shift) {
| 		&expression($1 || shift), next if (/^-e(.*)$/);
| 		&file($1 || shift), next if (/^-f(.*)$/);
| 		# ...
| 	}
| Unfortunately, this doesn't work properly for '-e0', '-f0', or '0'.
| 
| If strings weren't converted to numbers in boolean contexts . . .

while ($_ = shift) {
	&expression(length ? $_ : shift), next if s/^-e//;
	&file(length ? $_ : shift), next if s/^-f//;
	# ...

}

I just came up with this while replying.  Lemme know if you like it.
I like it so far... it looks pretty clean and direct.

$_ = "Just a sed user,";s/a/another/;s/sed/Perl/;s/user/hacker/;print
-- 
/=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) (03/29/90)

In article <1990Mar28.180657.22785@iwarp.intel.com>, merlyn@iwarp (Randal Schwartz) writes:
| while ($_ = shift) {
| 	&expression(length ? $_ : shift), next if s/^-e//;
| 	&file(length ? $_ : shift), next if s/^-f//;
| 	# ...
| 
| }
| 
| I just came up with this while replying.  Lemme know if you like it.
| I like it so far... it looks pretty clean and direct.

But of course, after testing it (*after* posting it, sigh... :-), I
find that I must put parens around length, as in (length), or make it
length($_).  Sigh.  Overloading of the '?' operator bit me again.
Sorry for the first posting being incorrect.

(And I'm supposed to have this syntax *mastered* by now? :-)

I did come up with an additional widget that you might find interesting:

@ARGV = ("-eE1","-e","E2","-fF1","-f","F2");  ## for demo purposes

sub handle_e { print "e: @_\n"; }
sub handle_f { print "f: @_\n"; }

while ($_ = shift) {
	$sub="handle_$1", do $sub ((length)?$_:shift), next if s/^-([ef])//;
	unshift(@ARGV,$_), last;
}

Try that.  (I actually did, this time... :-)

$_="reJ alounPt srhaetchr, ek";s/(..)(.)(..)/(print$2),$3.$1/eg;s/(.)(.)(.)/(print$2),$3.$1/eg;print
-- 
/=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!"=/

flee@shire.cs.psu.edu (Felix Lee) (03/29/90)

Randal L. Schwartz <merlyn@iwarp.intel.com> wrote:
> while ($_ = shift) {
>	&expression(length ? $_ : shift), next if s/^-e//;
>	&file(length ? $_ : shift), next if s/^-f//;
>	# ...
> }

Okay.  That looks pretty usable, if still somewhat frightening.  I'll
have to remember to use "length" rather than testing strings directly.
Note, the while loop should read:
	while (length($_ = shift))
to handle "0" arguments properly...
--
Felix Lee	flee@shire.cs.psu.edu	*!psuvax1!flee

merlyn@iwarp.intel.com (Randal Schwartz) (03/29/90)

In article <E-hyh#3@cs.psu.edu>, flee@shire (Felix Lee) writes:
| Randal L. Schwartz <merlyn@iwarp.intel.com> wrote:
| > while ($_ = shift) {
| >	&expression(length ? $_ : shift), next if s/^-e//;
| >	&file(length ? $_ : shift), next if s/^-f//;
| >	# ...
| > }
| 
| Okay.  That looks pretty usable, if still somewhat frightening.  I'll
| have to remember to use "length" rather than testing strings directly.
| Note, the while loop should read:
| 	while (length($_ = shift))
| to handle "0" arguments properly...

[See my other posting for a bug fix to the included code.]

The while loop should read instead:

	while (@ARGV) {
		$_ = shift;
		...
		...
	}

to handle zero-length arguments, if you're gonna get picky. :-)

($_="Just another Perl hacker,"); 0 while s#.# do {print $&;} #e,s/^1//;
-- 
/=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!"=/

flee@shire.cs.psu.edu (Felix Lee) (03/29/90)

Randal Schwartz <merlyn@iwarp.intel.com> wrote:
> The while loop should read instead:
>	while (@ARGV) {
>		$_ = shift;
>	}
> to handle zero-length arguments, if you're gonna get picky. :-)

Urf.  I'm too used to Icon's notion of success and failure, and I seem
to try to apply it to perl all the time, probably because perl has a
conciseness vaguely reminiscent of Icon.  I should back off and try
not to pack things so tightly.

undef$/.open($_='>TcUENMaQ$RraE9wDKkh',$0).grep(print(substr($_, (ord)-32,
1)),split(/c\s/,join(<$_>."c\t",split(//))))
--
Felix Lee	flee@shire.cs.psu.edu	*!psuvax1!flee