tags:

views:

394

answers:

7

In Perl, which of these is the "better" style?

$hash{"string"} or $hash{string}?

In any case, are they functionality identical?

+10  A: 

They're functionally identical, that is until your key has a space or some other non-alphanumeric character in it. Then you have to use the quoted approach.

I prefer to not quote and use names that contain alpha_num and the underscore. That lets me get away with not quoting most of the time.

Artem Russakovskii
They aren't functionally identical. In certain cases, you get the same result, but not for the same reason.
brian d foy
The question was whether $hash{"string"} is identical to $hash{string}, which it is.
Artem Russakovskii
+4  A: 

The latter format, $hash{string}, is more concise, but it only works for alphanumerics and underscores.

a paid nerd
+8  A: 

From perldata perldoc:

In fact, an identifier within such curlies is forced to be a string, as is any simple identifier within a hash subscript. Neither need quoting. Our earlier example, $days{'Feb'} can be written as $days{Feb} and the quotes will be assumed automatically. But anything more complicated in the subscript will be interpreted as an expression. This means for example that $version{2.0}++ is equivalent to $version{2}++, not to $version{'2.0'}++

So yes fundamentally identical. However beware of gotchas:

sub is_sub { 'Yep!' }

my %hash;
$hash{ is_sub   } = 'Nope';
$hash{ is_sub() } = 'it is_sub!!';

say Dumper \%hash;

Will show:

$VAR1 = { 'is_sub' => 'Nope', 'Yep!' => 'it is_sub!!' };

My preference is for the bareword... but remember those () or a preceding + (see jrockway's comment and answer) if you're calling a sub ;-)

/I3az/

draegtun
Your example regarding `$version{2.0}` vs. `$version{'2.0'}` is confusing to me considering this: `perl -e '$foo{'2.0'}=1; print $foo{'2'}++, $foo{2}++, $foo{2.0}++, $foo{1+1}++, "\n";'`The value in the braces is evaluated into a scalar and that scalar is used as the key. So I have to assume that you didn't test your example or that I'm missing something subtle in what you're trying to say. (For me it prints *1234*)
Jim Dennis
Unfortunately your example is incorrect. Actually I'm surprised it even parsed OK. U're using single quotes on the -e and in the hash index. Anyway if you check your $foo hash values after settings you get { '2.0' => 1, '2' => 4 }... which is the answer you would expect to see
draegtun
You can also write +function instead of function().
jrockway
More specific link: http://perldoc.perl.org/perldata.html#Scalar-value-constructors
Brad Gilbert
+7  A: 

Out of pedantry, I always quote my string references in a hash. It serves to ensure that I'm not going to have a gotcha[1].

[1]I'm pretty conservative in my Perl coding.

Paul Nathan
+1 because it's a legitimate argument even though I tend to disagree.
Chris Lutz
Do you disagree that it avoids certain gotchas? Or disagree on style grounds? I'm curious.
Paul Nathan
what gotchas exactly does always quoting avoid?
nohat
What if you have a sub baz() {return 1}? I have no idea what foo{baz} would do. I suspect baz gets interpolated into a string, but, then, I'm not sure. I know what foo{"baz"} does, and I know what foo{baz()} does.
Paul Nathan
$foo{baz} always means $foo{baz}. There isn't really any gotcha. I would say it's a gotcha if $foo{baz} sometimes meant something else, but it doesn't, so it's not.
nohat
+7  A: 

The form without quotes is preferred by most, because it's more concise and uncluttered, as long as the hash key is limited to alphanumerics and the underscore. Also, most any editor with Perl syntax support knows how to highlight these as strings despite them not being within quotes.

It should be noted that you can get this behavior not only when using hash keys, but when defining hashes, passing arguments, or even when defining lists when you use =>. It can help to visually distinguish your keys from your values in the former two cases. Examples:

# Hash construction
my %hash = ( 
    key1 => "val1",
    key2 => "val2" 
);

# Subroutine arguments
some_function( arg1 => "val1", arg2 => $val2);
sub some_function { my %args = @_; }; # arguments are pulled in as a hash

# List construction (of course, not sure why you'd do this...)
my @list = (Foo => "bar");
print @list; # prints Foobar

All that said, I started out quoting everything and it's been a hard habit to break. It somehow feels "safer" to quote your hash keys, even after all these years.

Adam Bellaire
Less error prone? I've seen more errors from people not using quotes than using them. See draegtun's answer for a few examples.
brian d foy
@brian: Yes, the two examples given are good, but not exactly obscure. A period is outside the set alphanum + underscore, so it's easy to catch. I also make it habit personally to always use parens with user-defined methods, so the second form doesn't get me either. However, I bow to your superior experience, and have removed that sentence from my response.
Adam Bellaire
+7  A: 

Avoiding the quotes is more idiomatic.

Edit to add:

Quoting is not the solution to absolute readability. Consider the inconsistency here:

sub function() { 'OH HAI' }
my @list = ('foo', 'bar', function); 
# ==> ('foo', 'bar', 'OH HAI')

my %hash;
$hash{'foo'} = 1;
$hash{'bar'} = 2;
$hash{function} = 3;
# ==> { foo => 1, bar => 2, function => 3 } (oops)

When you never quote strings, the "weird" things are visually different from the plain strings... and it is parsed correctly.

$hash{foo} = 1;
$hash{bar} = 2;
$hash{+function} = 3; # aha, this looks different... because it is
# ==> { foo => 1, bar => 2, 'OH HAI' => 3 }

(Stack Overflow's syntax highlighting fucks this up, so try to ignore it.)

jrockway
A: 

You should always $hash{"string"} unless you want $hash{string}

xxxxxxx