String Interpolation
SUBROUTINE INTERPOLATION IN PERL STRINGSEver tried to call a subroutine inside a double-quoted string and wondered why it didn't work? You're not alone. Perl's string interpolation is powerful, but it needs a little coaxing when it comes to subroutines.
Let's unlock this hidden gem together.
Part 1: THE PROBLEM
You might think this would work:But nope - that just prints the literal text "get_name()".say "Hello, get_name()!";
Perl interpolates variables like $name and @items, but it doesn't automatically recognize bare subroutine calls. We need to wrap them in a special syntax.
Part 2: SCALAR CONTEXT WITH \${\()}
When you want to interpolate a subroutine that returns a single value (scalar context), use the ${\()} construct:What's happening here? Let's break it down:sub get_greeting { return "Welcome to Perl"; } say "Hello! ${\(get_greeting())}"; # Output: Hello! Welcome to Perl
The backslash creates a reference, and ${ } dereferences it right back. It's a round trip that tricks Perl into evaluating your subroutine inside the string.${ ... } - Dereference a scalar reference \( ... ) - Create a reference to the result get_greeting() - Your subroutine call
Part 3: LIST CONTEXT WITH @{[]}
When your subroutine returns a list, or you want to preserve list context, use @{[]}:Want them comma-separated? Combine with join:sub get_top_cities { return ("Tokyo", "Paris", "New York"); } say "Cities: @{[get_top_cities()]}"; # Output: Cities: Tokyo Paris New York
The @{[]} construct works similarly:say "Cities: @{[join(', ', get_top_cities())]}"; # Output: Cities: Tokyo, Paris, New York
The square brackets capture the list into an arrayref, then @{ } expands it back into the string with spaces between elements (or whatever $" is set to).@{ ... } - Dereference an array reference [ ... ] - Create an anonymous array reference
Part 4: ANONYMOUS SUBROUTINES
You can even define and call anonymous subs inline:Or with list context:my $multiplier = 5; say "Result: ${\(sub { return 6 * $multiplier }->())}"; # Output: Result: 30
This is particularly handy for quick transformations without defining a named subroutine.say "Doubled: @{[map { $_ * 2 } (1, 2, 3)]}"; # Output: Doubled: 2 4 6
Part 5: PRACTICAL EXAMPLES
Timestamps in log messages:Dynamic pluralization:sub timestamp { my @t = localtime; return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]); } say "[${\(timestamp())}] Application started";
Conditional content:sub pluralize { my ($count, $word) = @_; return $count == 1 ? "$count $word" : "$count ${word}s"; } my $files = 7; say "Processing ${\(pluralize($files, 'file'))}..."; # Output: Processing 7 files...
my $user = "Alice"; my $is_admin = 1; say "Welcome, $user${\($is_admin ? ' (Administrator)' : '')}!"; # Output: Welcome, Alice (Administrator)!
Part 6: MEMORY AID
Here's a simple way to remember which to use:Both use the same principle: create a reference, then immediately dereference it inside the string.${\()} - Dollar sign for Scalar (single value) @{[]} - At sign for Array (list of values)
CONCLUSION
String interpolation with subroutines might look a bit cryptic at first, but once you understand the reference/dereference dance, it becomes second nature.
These constructs let you build dynamic strings without awkward concatenation or temporary variables. Clean, expressive, and very Perlish.${\(scalar_sub())} - for single values @{[list_sub()]} - for lists
perl.gg