kionysus has asked for the wisdom of the Perl Monks concerning the following question:

On box A I'm running: perl, v5.8.8 built for x86_64-linux-thread-multi

On box B I'm running: perl, v5.10.1 (*) built for x86_64-linux-thread-multi

Running perl -cw on box boxes says the script is clean and "use strict" is in play. After executing the script, I receive "Can't use string ("1") as an ARRAY ref while "strict refs" in use" on box B which wasn't happening on box A.

Looking through the perl changelog, I still cannot find what has changed that would cause this.

The issue is in the way that I've referenced array objects in a for loop:
for (my $i=0; $i <= $#{@alarms}; $i++) { print $alarms[$i]; }
I cannot for the life of me remember why I decided to referenc the array that way to get the index length, but I do know there was a change in the changelog that did away with $# and I'm wondering if this fell victim to that change. The solution is obviously changing the for loop to:
for (my $i=0; $i <= $#alarms; $i++) { print $alarms[$i]; }
Can anyone tell me what the difference between the array name front loaded by dollar-pound and encapsulated by curly braces than just dollar-pound-arrayname and why it no longer works?

Replies are listed 'Best First'.
Re: understanding curly braces surrounding an array
by davido (Cardinal) on Mar 08, 2012 at 23:10 UTC

    The first syntax: $#{@alarms} isn't much good for anything beyond obfuscation, and shouldn't pass strictures. I don't know if it worked in some way that it shouldn't have back when Perl 5.8.8 was current, but here's what I think it is, deobfuscated nowadays:

    @alarms in scalar context will yield the number of elements in @array. Let's say you have one element. So it returns the number 1.

    $#{....} will attempt to either dereference '....', or if it's not a reference, use '....' as a symbol. In this particular example, '....' happens to be the string '1'. '1' comes from the number of elements in @array.

    Using '1' as a symbol, and placing a $# sigil in front of it, you now have a symbolic reference. You're asking Perl what the highest index is in the array named @1. I can't think of any reason that there would be an array named @1, but it probably doesn't have any practical relationship to @array, so the code in your first example is useless.

    The usage is far enough off the beaten path that I could be wrong about how it's parsed, but that seems reasonable to me at the moment.


    Dave

Re: understanding curly braces surrounding an array
by GrandFather (Saint) on Mar 09, 2012 at 00:51 UTC

    Actually "the" solution is changing the for loop to:

    for my $alarm (@alarms) { print $alarm; }

    which even your C friends will understand, although they wouldn't write it that way. Or if you don't mind that your C friends may be fazed by a little Perl you could:

    print $_ for @alarms;
    True laziness is hard work

      Well, since nothing's being done with $_,:

      print @alarms;

      More "work" might make sense if you're trying to append a newline per iteration or something.


      Dave

        Indeed, although that doesn't contrast the Perl for loop constructs with the C construct used by the OP. ;) (And maybe, perhaps, the OP simplified his example code.)

        True laziness is hard work
Re: understanding curly braces surrounding an array
by JavaFan (Canon) on Mar 08, 2012 at 23:03 UTC
    It's a bug fix. For a long time, $#{@array} was identical to $#array. Which doesn't make sense. Perl 5.10 fixed this issue.