Some time ago it occurred to me that in a map()'s BLOCK a no (or use, for what that matters) statement "doesn't work", e.g.:
my %hash=map { no strict 'refs'; $_ => \&{$_}; } qw/sol1 sol2 .../; # Pseudo-code
I had brought this on clpmisc, at map()'s BLOCK [was: "Re: Q: re Inline and Benchmark"] (also available from Google or from Google-beta) and there were fundamentally two kind of reactions, as you can see by yourself:
  1. in Perl there are already so many deviations from orthogonality, that this is not that surprising after all,
  2. deviations from orthogonality generally serve the purpose of implementing dwimmeries, but one can't see how this could apply to the one under consideration, so it simply "shouldn't" be there...
What do you monks think about this?

Note: I do know that there are tons of other ways around the issue, e.g. with a do block and the EXPR-form of map.

Replies are listed 'Best First'.
Re: map()'s BLOCK and deviations from othogonality...
by rir (Vicar) on Feb 24, 2005 at 14:30 UTC
    Updated (per local argument on clarity):
    You are in map()'s EXPR form and so are not seeing the real problem.

    Disambiguate your expression:

    my %hash=map { ; # Disambiguator no strict 'refs'; $_ => \&{$_}; } qw/sol1 sol2 .../;
    Be well,
    rir
      You are in map()'s EXPR form and so are not seeing the real problem.

      Disambiguate your expression:

      my %hash=map { ; # Disambiguator
      Hmmm, I see that this does work. So basically you're saying that if don't put that disambiguator there, perl thinks it's the EXPR form of map() rather than the BLOCK form, notwithstandig the fact that there's no comma after the block itself. I think this is so because it begins to interpret the "no" as a hash(ref)'s key, right?

      All in all one the lesson we learn could be that "while nothing but perl can parse Perl, even perl sometimes has difficulties doing so"...

        This is even documented in perlref:
        Because curly brackets (braces) are used for several other +things including BLOCKs, you may occasionally have to disambiguate + braces at the beginning of a statement by putting a "+" or a "retu +rn" in front so that Perl realizes the opening brace isn't startin +g a BLOCK. The economy and mnemonic value of using curlies is +deemed worth this occasional extra hassle. For example, if you wanted a function to make a new hash an +d return a reference to it, you have these options: sub hashem { { @_ } } # silently wrong sub hashem { +{ @_ } } # ok sub hashem { return { @_ } } # ok On the other hand, if you want the other meaning, you can d +o this: sub showem { { @_ } } # ambiguous (currently o +k, but may change) sub showem { {; @_ } } # ok sub showem { { return @_ } } # ok The leading "+{" and "{;" always serve to disambiguate the +expres- sion to mean either the HASH reference, or the BLOCK.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

        So basically you're saying that if don't put that disambiguator there, perl thinks it's the EXPR form of map() rather than the BLOCK form, notwithstandig the fact that there's no comma after the block itself.

        That can't be. Indeed, Perl does make the decision before it is even close to worrying about the comma, but the comma must be there for an expression and must not be there for a block.

        So if you and Perl disagree on the expression vs. block interpretation, then the presense or lack of the comma will cause Perl to tell you quite loudly that it didn't agree with you (unless you get the comma's existence wrong compared to your desire for the expression vs. block form).

        So I've been assuming that one side or the other of this discussion hasn't actually tested the exact code under discussion. No, I haven't tested any of it.

        - tye