7

In Perl, is there any reason to encapsulate a single variable in double quotes (no concatenation) ?

I often find this in the source of the program I am working on (writen 10 years ago by people that don't work here anymore):

my $sql_host = "something";
my $sql_user = "somethingelse";

# a few lines down
my $db = sub_for_sql_conection("$sql_host", "$sql_user", "$sql_pass", "$sql_db");

As far as I know there is no reason to do this. When I work in an old script I usualy remove the quotes so my editor colors them as variables not as strings.

I think they saw this somewhere and copied the style without understanding why it is so. Am I missing something ?

Thank you.

daotoad
  • 26,689
  • 7
  • 59
  • 100
Radu Maris
  • 5,648
  • 4
  • 39
  • 54
  • 2
    This is a good question because the answers here show just how careful you should be when re-factoring old code - there just may be a good reason for something which at first appears like bad style. – tangent Feb 06 '12 at 20:21

5 Answers5

7

All this does is explicitly stringify the variables. In 99.9% of cases, it is a newbie error of some sort.

There are things that may happen as a side effect of this calling style:

my $foo = "1234";
sub bar { $_[0] =~ s/2/two/ }
print "Foo is $foo\n";
bar( "$foo" );
print "Foo is $foo\n";
bar( $foo );
print "Foo is $foo\n";

Here, stringification created a copy and passed that to the subroutine, circumventing Perl's pass by reference semantics. It's generally considered to be bad manners to munge calling variables, so you are probably okay.

You can also stringify an object or other value here. For example, undef stringifies to the empty string. Objects may specify arbitrary code to run when stringified. It is possible to have dual valued scalars that have distinct numerical and string values. This is a way to specify that you want the string form.

There is also one deep spooky thing that could be going on. If you are working with XS code that looks at the flags that are set on scalar arguments to a function, stringifying the scalar is a straight forward way to say to perl, "Make me a nice clean new string value" with only stringy flags and no numeric flags.

I am sure there are other odd exceptions to the 99.9% rule. These are a few. Before removing the quotes, take a second to check for weird crap like this. If you do happen upon a legit usage, please add a comment that identifies the quotes as a workable kludge, and give their reason for existence.

ikegami
  • 367,544
  • 15
  • 269
  • 518
daotoad
  • 26,689
  • 7
  • 59
  • 100
  • Re "If you are working with XS code that looks at the flags that are set on scalar arguments to a function", I previously showed a Pure Perl example. Anything that uses `ref()` would suffice. – ikegami Feb 06 '12 at 18:54
6

In this case the double quotes are unnecessary. Moreover, using them is inefficient as this causes the original strings to be copied.

However, sometimes you may want to use this style to "stringify" an object. For example, URI ojects support stringification:

my $uri = URI->new("http://www.perl.com");
my $str = "$uri";
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • It will also quietly turn an `undef` into an empty string if warnings haven't been enabled, won't it? I wouldn't call that a valid use though, I probably wouldn't consider anything without warnings cranked up to be valid. – mu is too short Feb 06 '12 at 09:16
  • @mu is too short: yes, `undef` will become `""` (regardless of whether warnings were enabled) – Eugene Yarmash Feb 06 '12 at 09:26
  • But it won't go quietly with warnings on, you'll get the "uninitialized value in concatenation" complaint. – mu is too short Feb 06 '12 at 09:28
  • @mu is too short, `$x //= '';` is better at stringifying undef than `$x = "$x";` because you don't have to turn off warnings to do it. – ikegami Feb 06 '12 at 09:31
  • Anything that requires a string would automatically stringify an object, so it's not something that would normally need to be done. – ikegami Feb 06 '12 at 09:38
  • 2
    @ikegami: But we're looking at historic code from the olden days before `//`. And vi beats emacs, Linux beats FreeBSD, and 11 angels can dance on the head of a pin :) – mu is too short Feb 06 '12 at 09:45
  • 1
    I can imagine an unfortunate collision of interfaces requiring explicit stringification of an object. Given such a circumstance, I would be inclined to make an explicit call to the class's underlying stringfication method: `my $str = $foo->as_string();` There may be cases where the stringifier is anonymous (don't do that!) or you rely on polymorphism between objects that don't share a common stringification method in their interfaces (sigh). In this case you have no choice but to do `my $str = "$foo"; # Intentionally stringify $foo - Foo::Bar needs curds but no whey` Note the comment. – daotoad Feb 06 '12 at 10:03
  • @mu is too short, Are you saying passing `""` for a DSN is better than passing `undef`? – ikegami Feb 06 '12 at 16:02
  • @ikegami: I'm saying that you're missing the point by focusing on the specific example rather than the general principle of "is there any reason to encapsulate a single variable in double quotes". – mu is too short Feb 06 '12 at 18:27
  • @mu is too short, huh? «`$x //= '';` is better at stringifying undef than `$x = "$x";`» is not a specific example. You're the one who brought up an example. And if you wish, `$x ||= '';` was usually better before `//` existed, and if not, you could use `defined($x) ? $x : ''`. – ikegami Feb 06 '12 at 18:50
6

I don't know why, but it's a pattern commonly used by newcomers to Perl. It's usually a waste (as it is in the snippet you posted), but I can think of two uses.


It has the effect of creating a new string with the same value as the original, and that could be useful in very rare circumstances.

In the following example, an explicit copy is done to protect $x from modification by the sub because the sub modifies its argument.

$ perl -E'
   sub f { $_[0] =~ tr/a/A/; say $_[0]; }
   my $x = "abc";
   f($x);
   say $x;
'
Abc
Abc

$ perl -E'
   sub f { $_[0] =~ tr/a/A/; say $_[0]; }
   my $x = "abc";
   f("$x");
   say $x;
'
Abc
abc

By virtue of creating a copy of the string, it stringifies objects. This could be useful when dealing with code that alters its behaviour based on whether its argument is a reference or not.

In the following example, explicit stringification is done because require handles references in @INC differently than strings.

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib $lib;
   use DBI;
   say "ok";
'
Can't locate object method "INC" via package "Path::Class::Dir" at -e line 4.
BEGIN failed--compilation aborted at -e line 4.

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib "$lib";
   use DBI;
   say "ok";
'
ok
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • The first case can be described as "workaround @_ aliasing with explicit copy". I would recommend to add comments in the code that does such things. – dolmen Feb 10 '12 at 10:41
  • @dolmen, Added description of the examples. – ikegami Feb 10 '12 at 19:51
2

In your case quotes are completely useless. We can even says that it is wrong because this is not idiomatic, as others wrote.

However quoting a variable may sometime be necessary: this explicitely triggers stringification of the value of the variable. Stringification may give a different result for some values if thoses values are dual vars or if they are blessed values with overloaded stringification.

Here is an example with dual vars:

use 5.010;
use strict;
use Scalar::Util 'dualvar';

my $x = dualvar 1, "2";
say 0+$x;
say 0+"$x";

Output:

1
2
dolmen
  • 8,126
  • 5
  • 40
  • 42
0

My theory has always been that it's people coming over from other languages with bad habits. It's not that they're thinking "I will use double quotes all the time", but that they're just not thinking!

I'll be honest and say that I used to fall into this trap because I came to Perl from Java, so the muscle memory was there, and just kept firing.

PerlCritic finally got me out of the habit!

It definitely makes your code more efficient, but if you're not thinking about whether or not you want your strings interpolated, you are very likely to make silly mistakes, so I'd go further and say that it's dangerous.

Bart B
  • 661
  • 8
  • 18