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

I'm wondering the straight poop on when quotes are needed for strings in list values and hash keys. In PHP, it's not enforced, but it's good form to quote your string literals so that they are not unintentionally interpolated if there is a string constant of the same name. Is this also true of Perl?

%hash = (key_is_unquoted => 42); # unquoted key name print "$hash{key_is_unquoted}\n"; # unquoted key, prints: 42 print "$hash{'key_is_unquoted'}\n"; # quoted key, prints: 42 %hash2 = ('key_is_quoted' => 255); # quoted key name print "$hash2{'key_is_quoted}'\n"; # quoted key, prints: 255 print "$hash2{key_is_quoted}\n"; # unquoted key, prints: 255 %hash3 = (key => value); # unquoted key and value print "$hash3{key}\n"; # unquoted key, prints: value print "$hash3{'key'}\n"; # quoted key, prints: value

So (apparently), Perl and PHP are similar in that quoting hash keys is not enforced, nor is quoting list values that are string literals? So then, that begs the logical question, is it considered good form to quote string literals in Perl (as in PHP) to avoid confusion with string constants, or is that a personal choice?

To add to the confusion, the qw() function turns whitespace-delimited unquoted string literals into a list of quoted string literals, if I'm not mistaken.

Your opinions and advice on this are appreciated. Thanks,
Erik

Replies are listed 'Best First'.
Re: quoting style for lists
by crenz (Priest) on Aug 01, 2002 at 16:20 UTC

    String literals need to be quoted in perl. But: (from perlop)

    The => digraph is mostly just a synonym for the comma operator. It's useful for documenting arguments that come in pairs. As of release 5.001, it also forces any word to the left of it to be interpreted as a string.

    If you would have used use warnings (and also use strict), perl would have aborted with the following message:

    Bareword "value" not allowed while "strict subs" in use at test.pl line 14. Execution of test.pl aborted due to compilation errors.

    Thus follows: use %a = (key => 'value');

Re: quoting style for lists
by Abigail-II (Bishop) on Aug 01, 2002 at 17:12 UTC
    First of all, in Perl there are no "string constants" (whatever that is). Perl doesn't require you to quote your strings, but it's considered good form to do. In fact, if you don't quote, -w will issue a warning (usually, it's Perl so there are exceptions), and with "use strict", you will get a compile time error. (Note that you can only use unquoted strings if the strings look like valid identifiers, possibly preceeded by a minus sign).

    However, there are two exceptions. If a string looks like a valid identifier it doesn't have to be quoted if it's either used as a hash key, or on the left side of a fat arrow (=>). This is done to help the programmer; there is little room for mistakes here, when used as a hash key, you usually mean to use the string, not to call a possible function with that name (called without arguments). If you do want to call such a function, you can always preceed it with a +, or a put () behind it.

    the qw() function turns whitespace-delimited unquoted string literals into a list of quoted string literals, if I'm not mistaken.
    You are very mistaken. You are confusing syntax with semantics. qw returns a list of strings. Strings are values. The different forms of string literals (bareword, single quoted, double quoted, here document) are syntax constructs, but once compiled, there's no difference.

    Abigail

      If a string looks like a valid identifier it doesn't have to be quoted if it's either used as a hash key, or on the left side of a fat arrow (=>).

      Isn't a string on the left side of a fat arrow a hash key? Or is there a subtle difference that I'm missing...

      You are very mistaken. You are confusing syntax with semantics. qw returns a list of strings.

      Forgive me, but this is still confusing to me. My understanding is that qw accepts whitespace-separated "words" and returns a list of quoted "words". I'm not sure how this differs from what you just wrote.

      Thanks for everyone's input on this,

      Erik

        $, = " "; print I => do => not => think => so => "\n"; __END__ I do not think so
        As for qw, it is a quoting construct, like q, qq, etc. It's "argument" (which doesn't include the delimiters - the delimiters are eaten by the parser) is treated as a string and split on whitespace. What results is a list of strings.

        Note that as soon as the parser consumed it, the delimiters are gone, and they never return. Delimiters are there just there to tell the parser, "start here" and "stop here". It doesn't make sense for qw to return "quoted words", just like it doesn't make sense to let qw return yellow.

        Abigail

        Isn't a string on the left side of a fat arrow a hash key? Or is there a subtle difference that I'm missing...

        There is a subtle difference. The fat arrow is idiomatically used when declaring hashes, but it's not necessary, nor is that its only purpose.

        my %hash = ('foo', 1, 'bar', 2); my @args = ( foo => bar => baz ); use Data::Dumper; print Data::Dumper->Dump([ \%hash, \@args ], [ hash => 'args' ]);

        On =>

        Technically, => is a "funky comma". Yes, it is true that most of the time it is used for hash declarations, but you could use it for other purposes as well. And on the other hand, you can also declare a hash using

        %a = ('key', 'value');

        On qw

        Let's use perlspeak. qw returns a list of scalars (that is then stored in an array). Also, the quoting is only used for perl to recognize the string. When perl stores the string in memory, the quotes are of course not used anymore.

        @a = ('a', 'b', 'c'); @b = qw(a b c); # a and b contain the same elements %hash{key}++; %hash{'key2'}++; print "$_\n" foreach (keys %hash); # prints (not necessarily in this order): # key # key2

        Does this clarify your problem?

        Update: I didn't close my <b> tags, and I didn't use perlspeak myself -- perl uses lists rather than arrays. Thanks, Chmrr!

        Update 2:
        Chmrr says: Hrm -- it's not that perl uses lists rather than arrays; they're two different things, and perl has both. An array is @foo; a list is (1,2,3). Arrays are mutable, lists are not.
        Never argue with a saint ;-). Yes, he's right. And I learned something new. Thanks!

Re: quoting style for lists
by fruiture (Curate) on Aug 01, 2002 at 16:32 UTC

    If I'm not completely misled: The => operator causes it's left operand to be seen as string as long as it only contains \w-characters and perhaps a leading -minus. The same rules afaik apply for $hash{keys}. In any other position you will get a bareword error from strict, which is in use anyway ;)

    print Hello => ", $name\n"; %hair = ( Peter => 'green', Charles => white => ucfirst('mary') => 're +d' ); print "your hair is ",$hair{$name},"\n", "Peter's hair is ",$hair{Peter},"\n";
    --
    http://fruiture.de
      The => operator causes it's left operand to be seen as string as long as it only contains \w-characters and perhaps a leading -minus. The same rules afaik apply for $hash{keys}. In any other position you will get a bareword error from strict, which is in use anyway ;)
      Well, it's a bit more complicated. Watch:
      #!/bin/sh for word in 'foo' '-foo' 'foo::bar' '-foo::bar' 'FOO' do code='$_ = '$word'; print' for args in ' ' '-w' '-Mstrict' '-Mstrict -w' do cmd="perl $args -le '$code'" echo $cmd eval $cmd echo done done
      Running this gives:
      perl -le '$_ = foo; print'
      foo
      
      perl -w -le '$_ = foo; print' 
      Unquoted string "foo" may clash with future reserved word at -e line 1.
      foo
               
      perl -Mstrict -le '$_ = foo; print'
      Bareword "foo" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
      
      perl -Mstrict -w -le '$_ = foo; print'
      Bareword "foo" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
       
      perl -le '$_ = -foo; print'
      -foo
       
      perl -w -le '$_ = -foo; print'
      -foo
       
      perl -Mstrict -le '$_ = -foo; print'
      -foo
      
      perl -Mstrict -w -le '$_ = -foo; print'
      -foo
               
      perl -le '$_ = foo::bar; print'
      foo::bar
      
      perl -w -le '$_ = foo::bar; print'
      foo::bar
      
      perl -Mstrict -le '$_ = foo::bar; print'
      Bareword "foo::bar" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
      
      perl -Mstrict -w -le '$_ = foo::bar; print'
      Bareword "foo::bar" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
       
      perl -le '$_ = -foo::bar; print'
      -foo::bar
      
      perl -w -le '$_ = -foo::bar; print'
      -foo::bar
               
      perl -Mstrict -le '$_ = -foo::bar; print'
      -foo::bar
      
      perl -Mstrict -w -le '$_ = -foo::bar; print'
      -foo::bar
      
      perl -le '$_ = FOO; print'
      FOO
      
      perl -w -le '$_ = FOO; print'
      FOO
      
      perl -Mstrict -le '$_ = FOO; print'
      Bareword "FOO" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
      
      perl -Mstrict -w -le '$_ = FOO; print'
      Bareword "FOO" not allowed while "strict subs" in use at -e line 1.
      Execution of -e aborted due to compilation errors.
               
      
      Interesting, isn't? (And yes, there are good reasons why Perl behaves this way - I won't tell you know, think about it for a while)

      Abigail

        I see, what use should any unary '-' with bareword have apart from being a shell-option-like string? Thanks.
        But even the use of -barewords at other positions than before => and inside $hash{keys} is hairy anyway:

        use strict; use warnings; sub foo(){ 'x' } $_ = -foo; # Ambiguous use of -foo # resolved as -&foo() at ./ol line 8. print; # '-x' sub bar() { -1 } $_ = -bar; #Ambigous ... as -&bar() ... print; # 1 !not "--1" my %h = ( -foo => 'FOO' ); print keys %h,' : ',$h{-foo}; # '-foo : FOO'

        So to be on the safe side one should quote at these points, because if there is a reserved word 'foo' in the future, you will have a problem writing -foo barely.

        --
        http://fruiture.de