20

How can I resolve this case of "Useless use of a variable in a void context"?

For example:

  my $err = $soap_response->code, " ", $soap_response->string, "\n";
  return $err;

I get warnings like "Useless use of a variable in a void context"? Why? How can I resolve it?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
joe
  • 34,529
  • 29
  • 100
  • 137

3 Answers3

27

In case you want to concatenate the arguments, use the "." operator or join:

my $err = $soap_response->code. " ". $soap_response->string. "\n";
my $err = join '', $soap_response->code, " ", $soap_response->string, "\n";

Next is why Perl gives you warnings.

You're assigning to a scalar variable $err, and the right-hand side of the assignment is evaluated in scalar context.

Binary "," is the comma operator. In scalar context it evaluates its left argument in void context, throws that value away, then evaluates its right argument in scalar context and returns that value.

Evaluating a variable or a constant and throwing that value away is useless. And perl warns you about this.

FYI: Another possible issue with your code:

my $err = $soap_response->code, " ", $soap_response->string, "\n";

The assignment has higher precedence so that is:

(my $err = $soap_response->code), " ", $soap_response->string, "\n";

See Perl operators and precedence and the Comma operator for more information.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 2
    Great answer. But 'the right argument' is a bit ambiguous. Its assigning the wrong value and not the right one :). Try, perhaps, 'right-most' or 'final' or 'last' or something. – daotoad Feb 26 '10 at 16:17
  • 1
    I'd really like this answer better if it included mention of the concatenation operator as "this is what you meant". – darch Feb 26 '10 at 20:04
  • 1
    This is a better explanation of what went wrong, but codaddict has a better solution. `join` is just overkill here. What he really wanted was the concatenation operator, `.`. – cjm Feb 26 '10 at 22:24
16

I guess you wanted to concatenate the string pieces to form the entire error message, so you'll have to use the dot instead of comma:

my $err = $soap_response->code. " ". $soap_response->string. "\n";
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • 3
    @ephemient: That is not at all the same thing as the original code. Method calls are not hash lookups (even if the method just does a hash lookup, it might change in the future). – cjm Feb 26 '10 at 19:39
  • @cjm Those aren't method calls, try it yourself. `$$_{key}` is `${$_}{key}` is `$_->{key}`, except that the latter is a little more work to interpolate into a string. `perl -e'$_ = {key=>1}; print $$_{key}, ${$_}{key}, $_->{key}'` ==> 111 – ephemient Feb 26 '10 at 20:38
  • 1
    @ephemient, the point is that the original code in the OP *is* using method calls, not hash lookups. – friedo Feb 26 '10 at 20:46
  • @friedo @cjm Oh, I *totally* missed that. Waugh. `"${\scalar $soap_response->code} ${\scalar $soap_response->string}\n"` but that's actually pretty damn ugly. – ephemient Feb 26 '10 at 21:00
3
my $err = join(' ', $soap_response->code, $soap_response->string) . "\n";

or, better IMO:

return sprintf "%s %s\n", $soap_response->code, $soap_response->string;

See perldoc -f join and perldoc -f sprintf perldoc perlop.

Regarding the warning, see perldoc perlop and this note on the comma operator.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339