David W.
David W.

Reputation: 107040

Concatenating strings in Perl with "join"

See Update Below

I am going through a whole bunch of Perl scripts that someone at my company wrote. He used join to concatenate strings. For example, he does this (taken hot out of a real Perl script):

$fullpath=join "", $Upload_Loc, "/", "$filename";

Instead of this:

$fullpath = "$Upload_Loc" . "/" . "$filename";

Or even just this:

$fullpath = "$Upload_Loc/$filename";

He's no longer here, but the people who are here tell me he concatenated strings in this way because it was somehow better. (They're not too clear why).

So, why would someone use join in this matter over using the . concatenate operator, or just typing the strings together as in the third example? Is there a valid reason for this style of coding?

I'm trying to clean up lot of the mess here, and my first thought would be to end this practice. It makes the code harder to read, and I'm sure doing a join is not a very efficient way to concatenate strings. However, although I've been writing scripts in Perl since version 3.x, I don't consider myself a guru because I've never had a chance to hang around with people who were better than Perl than I am and could teach me Perl's deep inner secrets. I just want to make sure that my instinct is correct here before I make a fool of myself.

I've got better ways of doing that around here.


Update

People are getting confused. He isn't just for concatenating paths. Here's another example:

$hotfix=join "", "$app", "_", "$mod", "_", "$bld", "_", "$hf", ".zip";

Where as I would do something like this:

$hotfix = $app . "_"  $mod . "_" . $bld . "_" . "$hf.zip";

Or, more likely

$hotfix = "${app}_${mod}_${bld}_${hf}.zip";

Or maybe in this case, I might actually use join because the underscore causes problems:

$hotfix = join("_", $app, $mod, $bld, $hf) . ".zip";

My question is still: Is he doing something that real Perl hackers know, and a newbie like me who's been doing this for only 15 years don't know about? Do people look at me concatenating strings using . or just putting them in quotes and say "Ha! What a noob! I bet he owns a Macintosh too!"

Or, does the previous guy just has a unique style of programming much like my son's unique style of driving includes running head on into trees?

Upvotes: 8

Views: 24075

Answers (7)

ysth
ysth

Reputation: 98398

While recognizing that in all the examples I see here, there are no significant performance differences, a series of concatenation, whether with . or with double-quotish interpolation, is indeed going to be more memory-inefficient than a join, which precomputes the needed string buffer for the result instead of expanding it several times (potentially even needing to move the partial result to a new location each time).

I have a problem with the criticism I see leveled here; there are many right ways to speak perl, and this is certainly one of them.

Inconsistent indentation, on the other hand...

Upvotes: 1

Simon Whitaker
Simon Whitaker

Reputation: 20566

I've done my fair share of commercial Perl development for "a well known online retailer", and I've never seen join used like that. Your third example would be my preferred alternative, as it's simple, clean and readable.

Like others here, I don't see any genuine value in using join as a performance enhancer. It might well perform marginally better than string interpolation but I can't imagine a real-world situation where the optimisation could be justified yet the code still written in a scripting language.

As this question demonstrates, esoteric programming idioms (in any language) just lead to a lot of misunderstanding. If you're lucky, the misunderstanding is benign. The developers I enjoy working alongside are the ones who code for readability and consistency and leave the Perl Golf for the weekends. :)

In short: yes, I think his unique style is akin to your son's unique style of driving. :)

Upvotes: 6

Sinan Ünür
Sinan Ünür

Reputation: 118128

I would consider

$fullpath = join "/", $Upload_Loc, $filename;

clearer than the alternatives. However, File::Spec has been in the core for a long time, so

use File::Spec::Functions qw( catfile );
# ...
$fullpath = catfile $Upload_Loc, $filename;

is much better. And, better yet, there is Path::Class:

use Path::Class;

my $fullpath = file($Upload_Loc, $filename);

Speed is usually not a factor I consider in concatenating file names and paths.

The example you give in your update:

$hotfix=join "", "$app", "_", "$mod", "_", "$bld", "_", "$hf", ".zip";

demonstrates why the guy is clueless. First, there is no need to interpolate those individual variables. Second, that is better written as

$hotfix = join '_', $app, $mod, $bld, "$hf.zip";

or, alternatively, as

$hotfix = sprintf '%s_%s_%s_%s.zip', $app, $mod, $bld, $hf;

with reducing unnecessary punctuation being my ultimate goal.

Upvotes: 4

tchrist
tchrist

Reputation: 80384

Perl compiles double-quoted strings into things with join and . catenation in them:

$ perl -MO=Deparse,-q -e '$fullpath = "$Upload_Loc/$filename"'
$fullpath = $Upload_Loc . '/' . $filename;
-e syntax OK

$ perl -MO=Deparse,-q -le 'print "Got @ARGV"'
BEGIN { $/ = "\n"; $\ = "\n"; }
print 'Got ' . join($", @ARGV);
-e syntax OK

which may inspire you to things like this:

$rx = do { local $" = "|"; qr{^(?:@args)$} };

as in:

$ perl -le 'print $rx = do { local $" = "\t|\n\t"; qr{ ^ (?xis: @ARGV ) $ }mx }' good stuff goes here
(?^mx: ^ (?xis: good    |
        stuff   |
        goes    |
        here ) $ )

Nifty, eh?

Upvotes: 3

Eric Strom
Eric Strom

Reputation: 40142

In general, unless the lists of items to be joined are huge, you will not see much of a performance difference changing them over to concatenations. The main concern is readability and maintainability, and in those cases, if the string interpolation form is clearer, you can certainly use that.

I would guess that this is just a personal coding preference of the original programmer.

In general, I use join when the length of the list is large/unknown, or if I am joining with something other than the empty string (or a single space for array interpolation). Otherwise, using . or simple string interpolation is usually shorter and easier to read.

Upvotes: 3

Cfreak
Cfreak

Reputation: 19309

Interpolation is a little slower than joining a list. That said I've never known anyone to take it to this extreme.

You could use the Benchmark module to determine how much difference there is.

Also, you could ask this question over on http://perlmonks.org/. There are real gurus there who can probably give you the inner secrets much better than I can.

Upvotes: 1

Alex Brown
Alex Brown

Reputation: 42872

All of those approaches are fine.

Join can sometimes be more powerful than . concatentate, particularly when some of the things you are joining are arrays:

join "/", "~", @document_path_elements, $myDocument;

Upvotes: 0

Related Questions