Pit
Pit

Reputation: 1488

Concatenating multiple values returned by function with multiple variables without using temporary variables

I have a function like

sub multi_return {
    my ($val1, $val2) = ('','');
    #does something
    return ($val1, $val2);
}

Is there a way I can concatenate both returned vales with different string variables without having to use temporary variables?

my $string1 = 'some text';
my $string2 = 'some other text';
my ($tmp1,tmp2) = multi_return();
$string1 .= $tmp1;
$string2 .= $tmp2
undef($tmp1);
undef($tmp2);

This does not work

($string1, $string2) = multi_return();

Edit:

More generally, I'm searching for a way to concatenate two lists of strings, where both lists have the same length. The strings on the same positions of each list should be concatenated.

I guess the second part of @amon's answer serves my purpose.

Upvotes: 1

Views: 942

Answers (3)

AdrianHHH
AdrianHHH

Reputation: 14076

You can declare the temporary variables in a block so that they are not available to the rest of the block of code

my $string1 = 'some text';
my $string2 = 'some other text';
{
    my ($tmp1,tmp2) = multi_return();
    $string1 .= $tmp1;
    $string2 .= $tmp2
}

Upvotes: -2

TLP
TLP

Reputation: 67910

I think you are overthinking this. Why not just pass the strings to the subroutine, concatenate inside, and then assign them the return value? Like this:

my $str1 = "foo";
my $str2 = "bar";
my @args = qw(something else you need);

($str1, $str2) = multi_return($str1, $str2, @args);
# $str1 == "foosomething";
# $str2 == "barsomething else"

sub multi_return {
    my ($str1, $str2, @args) = @_;
    $str1 .= "something";
    $str2 .= "something else";
    .... # etc
    return ($str1, $str2);
}

On a related note, your code:

my $string1 = 'some text';
my $string2 = 'some other text';
my ($tmp1,tmp2) = multi_return();
$string1 .= $tmp1;
$string2 .= $tmp2
undef($tmp1);
undef($tmp2);

Is better written like this:

my $string1 = 'some text';
my $string2 = 'some other text';
{
    my ($tmp1, $tmp2) = multi_return();
    $string1 .= $tmp1;
    $string2 .= $tmp2;
}

Lexical variables are restricted to the scope where they are defined, in this case the surrounding block we placed around it. With your code, the variables $tmp1 and $tmp2 are still in scope, where they can possibly mess things up.

Upvotes: 2

amon
amon

Reputation: 57640

What you ask is not generally possible. However, we can do some looping to abstract over the number of return values:

my @strings = ("some text", "some other text");
my @ret = multi_return;
$strings[$_] .= $ret[$_] for 0 .. $#strings;

We can write a sub that in turn abstracts over that:

sub append_all {
  my $suffixes = shift;
  $_ .= shift @$suffixes for @_; # uses aliasing behaviour to modify out-args
}

my $string1 = "some text";
my $string2 = "some other text";

append_all([multi_return()] => $string1, $string2);

Upvotes: 4

Related Questions