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

This simple code fails with an error.
my %hash = (1,'a',2,'b',3,'c'); foreach keys(%hash) { print }
but the error message is "Missing $ on loop variable."

my %hash = (1,'a',2,'b',3,'c'); foreach (keys(%hash)) { print }
works just fine.

Why is the error message about missing dollar signs, not missing brackets?

This is Perl 5.6.1



($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print

Replies are listed 'Best First'.
Re: Missing $ on loop variable?
by hardburn (Abbot) on Nov 05, 2003 at 20:50 UTC

    Since foreach can optionally take a variable on the outside, perl interprets keys as the name of that variable, with the parans around %hash indicating the array you want to iterate over. In other words, it was expecting this:

    foreach $keys (%hash) { . . . }

    But since it didn't see the sigal, it threw an error about that.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: Missing $ on loop variable?
by qq (Hermit) on Nov 05, 2003 at 21:59 UTC
    perl -e'%hash=(1,"a",2,"b",3,"c"); foreach keys ( %hash ) { print }' Missing $ on loop variable at -e line 1. perl -e'%hash=(1,"a",2,"b",3,"c"); foreach ( %hash ) { print }' 1a3c2b perl -e'%hash=(1,"a",2,"b",3,"c"); foreach $keys ( %hash ) { print $ke +ys }' 1a3c2b perl -e'%hash=(1,"a",2,"b",3,"c"); foreach ( keys %hash) { print }' 132

    Nothing wrong with ( %hash ), but keys looks like a loop variable in that context (as hardburn describes well).

    Warnings and error messages are usually complaining about the right thing (at least in some way). If you think its wrong, read it again. I speak from personal experience of being too ready to disbelieve error codes. More often than not the simplest reading is the right one.

      Particularly true because in other languages (namely Bourne shell), you leave off the $ on loop variables, and many Perl newcomers over the years have been confused by that.

        Thanks all of you, particularly Schemer for a quick and straightforward answer, and Anonymous Monk for the explanation of why it might be a useful error message for someone coming from a shell scripting background.

        I still think perhaps "something between foreach and a list which is not a variable" would be a better error message though. I saw this construct as foreach, followed by something that I know returns a list, keys(%hashname), where's the error? It's kind of counter-intuitive for me at least.



        ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print
Re: Missing $ on loop variable?
by Anonymous Monk on Nov 05, 2003 at 20:54 UTC

    You don't have missing brackets (assuming you mean parentheses) per se. You have the foreach key word and you have a perfectly valid parenthesised list. Between those two syntactic elements should lie nothing or an explicitly named loop variable. You have neither.