in reply to Anon. array of refs to a range generated list of scalars.

I think this is a "bug", but not necessary to be a bug introduced during the implementation phase. This most likely is a bug introduced at the spec phase, or it is something never clearly defined. (At the end of this post, I have another exapmple)

One of the benefit we get from Perl is that it has very "rich" syntax, many shortcuts... However this may come back and bite us, or to be more precise bite Perl, not really us.

The richness of Perl's syntax actually sacrifices the rightness of its syntax to a certain level.

Thanks for BrowserUK, I tried this piece of code, base on his thought:
use Data::Dumper; { $a = 1; $b = 2; $c = 3; @a = \($a,$b, $c); print @a, "\n";#this is an array of ref } { $a = 1; $b = 2; $c = 3; $d = [\($a,$b, $c)]; print @$d, "\n";#this is an array of ref } { @a = \(1..3); print Dumper(@a);#this is an ref to an array }
This does not make sense to me at all. One may come up with some explanation for this, but I would not buy any explanation.

My philosophy is simple:
  1. Good syntax should be consistant all the way
  2. What I actually get matches what I see
Another example of bad syntax: the other day I tried redo within a do {} until block, but Perl complains that I could not use redo outside a loop block, which means Perl does not take do {} until as a loop block.

Thanks for gjb, he explained to me that he experienced the same problem a while back, and he figured out that is what Perl does, and it does not take do {} until as a loop block.

So it is not a bug, it is a feature, from the view of Perl's implementation phase, but this syntax is definitely flawed. It does not make any sense that, a do {} until block is not a loop block, when I am clearly using it for ITERATING.

Update

This is a very high-yielding discussion, and I must say I learned lots, thanks fellows.

However my point still stands. My point is regardless what is making the iteration, regardless what is being iterated, regardless whether the iteration is IMPLICIT or explicit, Perl actually knows there is a BLOCK it should iterate through, and in fact it is doing that iteration for us, then redo is within a loop block (or to be precise, a loop block Perl refused to recognize, although obviously it recognized and LOOP's thru), so redo should be handle as usual.

This is what I expected to happen, ;-) I still think it is what should happen.

Replies are listed 'Best First'.
Re: Re: Anon. array of refs to a range generated list of scalars.
by Hofmator (Curate) on Jan 18, 2003 at 18:57 UTC
    Another example of bad syntax: the other day I tried redo within a do {} until block, but Perl complains that I could not use redo outside a loop block, which means Perl does not take do {} until as a loop block.
    That is documented behaviour (see perlsyn), though I must agree not very consistent. It applies not only to do {} until but also to do {} while. perlsyn suggests a workaround like this
    do {{ next if /^#/; # do something }} until /^\s*$/;
    but you have to adjust this to be able to use last.

    My suggestion is to not use those constructs altogether and instead emulate them with bare blocks and redo ...

    # do {} while condition { # some code redo if condition; } # do {} until condition { # some code redo unless condition; }

    -- Hofmator

      Argh. Please don't use naked blocks with redo as loops, it's a nightmare to read. When I see a naked block, I expect to be looking at a private lexical scope, not an unadorned loop. If you need next, wrap the inner part with a naked block:
      do {{ $bar; baz() or next; }} while $foo;
      If you need last, wrap the whole thing:
      { do { $bar; baz() and last; } while $foo; }
      Of course, if you need both, it does get awfully clumsy:
      LOOP: { do {{ $bar; baz() or next; quux() and last LOOP; }} while $foo; }
      In that case, and if you're so inclined then maybe in the other cases as well, I propose:
      while(1) { $bar; baz() or next; quux() and last; }
      At least it documents the loop nature of the block, even if the break condition is again somewhat hidden.

      Makeshifts last the longest.

        well, some people think differently ... and you could always mark the bare block with a label, clearly stating what you want to do
        LOOP: { # some code redo LOOP if condition; } # that's actually quite close to perl6 ;-) loop { # some code last unless condition; }

        -- Hofmator

Re: Re: Anon. array of refs to a range generated list of scalars.
by BrowserUk (Patriarch) on Jan 18, 2003 at 19:06 UTC

    I think the thing with the do {} syntax is that you aren't iterating with the do block.

    You are iterating the do block itself.

    For example:

    $i=5; print do{ --$1 }; # prints 4 $i=5; print do{ --$i } while $i; # prints 43210

    However, this is directly analogous to

    $i=5; print --$1; # prints 4 $i=5; print --$i while $i; # prints 43210

    In the latter example, its very clear that the while modifier form is iterating the print.

    The former example, the while modifier is iterating the print also. It just so happens that the print has a do block as one of its terms. This is made clearer if you use the brackets on the print function like this.

    $i=5; print( do{--$i;} ) while $i;

    The confusion comes because we often format the construct like this

    $i=5; do { print --$i; } while ($i);

    Which makes it look like an iterate-at-least-once version of

    $i = 5; while ($i) { print --$i; }

    But you can show the difference by doing

    my ($i, $j) = (5, 0); $j += do { print --$i; } while ($i); print $j; # prints 5.

    Where the value 5 comes from the accumulation of the five 'successful' (1) return codes from the print function.

    Additionally

    If there is an inconsistancy with do, it's that the way it operates as an rvalue, makes it look somewhat analogous to the sort, map & grep functions, in as much as I half expected

    print do( 'fred' ); to work like print do{ 'fred' } Somewhat like

     print map $_, 'fred'; is similar to print map{ $_ } 'fred';.

    Actually, the error message from

     print do( 'fred' ); confuses me completly.


    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      Actually, the error message from print do( 'fred' ); confuses me completly.
      What error message? You are aware of the different variants of do? From perldoc -f do
      do BLOCK [...] do SUBROUTINE(LIST) [...] do EXPR Uses the value of EXPR as a filename and executes the contents of the file as a Perl script.
      so probably the file named 'fred' doesn't exist and do returns simply undef - at least that's what it does here (on perl 5.6.0) generating thus a warning about Use of uninitialized value in print ...

      -- Hofmator

        Your right of course, I didn't think about the do EXPR; form at all.

        If I do print do('fred')|| warn $!;

        I get No such file or directory at ...


        Examine what is said, not who speaks.

        The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.