[comp.lang.perl] Elegance: different aspect of next bug and elegent thingy..

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (03/14/91)

In article <28041@fs2.NISC.SRI.COM> cwilson@NISC.SRI.COM (Chan Wilson [Animal]) writes:
:     &input($labeltype) || {&Bzzzt; &WhatToPrint;}
: 	 		 ^^^^^^^^^^^^^^^^^^^^^^^^^ offending part
: }

A BLOCK is not an expression.  To evaluate a BLOCK as part of an
expression you have to put a do in front of it:

    &input($labeltype) || do {&Bzzzt; &WhatToPrint;}

: Naturally, I discovered that I can't do that.  So I rewrote a few
: things:
: 
: sub Bzzzt {
:     print stderr "\n\007<Bzzzt>  I need an answer here...\n\n";
:     do $_[0];
: }
: 
: 
: sub WhatToPrint {
: [.....]
:     &input($labeltype) || &Bzzzt(WhatToPrint);
: 
: 
: which had the _very_ interesting aspect of re-entering WhatToPrint at
: the next executable line.  It looks like this is another facet of the
: next bug.

Not really.

This code is not doing what you want at all--it's looking for a file called
WhatToPrint to evaluate, and not finding it, and returning.  You should
have said

	local($subname) = @_;
	do $subname();

The parens are required with do.  I discourage people from calling subroutines
with do any more for just this reason.  & doesn't require parens:

	local($subname) = @_;
	&$subname;

: But the elegent (IMHO, naturally) thing is what I came up with next.
: I restored Bzzzt to original, and without really thinking, re-wrote
: WhatToPrint to say:
: 
: sub WhatToPrint {
: [.....]
:     &input($labeltype) || &Bzzzt && &WhatToPrint;
: 
: 
: which reads as "Do sub input with $labeltype.  if 0 is returned, do
: Bzzzt _AND_ do WhatToPrint", which is what I intended, but certainly
: not what perl is interpreting it as.

That's precisely what perl is interpreting it as, as long a Bzzzt returns
a true value, which the print conveniently supplies.  Remember that &&
has higher precedence than ||, so it naturally groups the same as

    &input($labeltype) || (&Bzzzt && &WhatToPrint);

: Interesting, no?  Seems to me this is a way around the `mumble || {foo}'
: restriction...

That's one way to do it.  You also could have just said

    &input($labeltype) || (&Bzzzt, &WhatToPrint);

But why use recursion when simple iteration will do?

    until (&WhatToPrint, &input($labeltype)) { &Bzzzt; }

Larry