2

Here is the code to reproduce the problem:

sub hello { return (h => 1, n => 1); }
print join ", ", values hello();

I get the error:

Type of arg 1 to values must be hash (not subroutine entry) at - line 4, near ");" Execution of - aborted due to compilation errors.

I know I can break the call and the print on two lines:

sub hello { return (h => 1, n => 1); }
my %hash = hello();
print join ", ", values %hash;

But I don't want to do that. Is there some way to do this in one line so that I don't have to create temporary variables all the time?

tster
  • 17,883
  • 5
  • 53
  • 72

4 Answers4

9

You could use hash references:

sub hello { return {h => 1, n => 1}; }
print join ", ", values %{hello()};

but otherwise, no. Perl may interpret the return value of a subroutine in either scalar or list context, but there is no concept of returning a value in a hash context.


Update: this also works

sub hello { return (h => 1, n => 1); }
print join ", ", values %{{hello()}};

The inner {} converts the output of hello() from a list into a hash reference. The outer %{} dereferences the hash.

(Does %{{}}} count as a pseudo-operator?)

Community
  • 1
  • 1
mob
  • 117,087
  • 18
  • 149
  • 283
8

I don't see the usefulness in a real program, but yes, it is possible.

print join ", ", values %{{hello()}};

Explanation: hello() is a list; {hello()} is a hash reference; %{{hello()}} is a hash.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • It's useful in real programs all the time. If you are getting returned a hash from an API and all you need are the keys or the values. – tster Jul 30 '10 at 20:26
  • @tster: that's different. Certainly `%{sub_returning_hash()}` is useful. But the question is about a sub returning a plist (i.e., a list containing successions of keys and values), and that's not common in Perl. – Gilles 'SO- stop being evil' Jul 30 '10 at 20:51
  • A function which returns a hash is no different than a function which returns an array to the calling function. Plus, functions which return hashes might be uncommon in your perl, but I deal with a lot of them. – tster Jul 31 '10 at 12:03
2

Another thing that you could do is use a toggle variable.

sub hello { return (h => 1, n => 1); }
my $toggle = 1;
print join ", ", grep { $toggle = !$toggle; } hello();

Another thing you could do is use List::Pairwise

use List::Pairwise qw<mapp>;
print join ", ", mapp { $b } hello();

I had been looking for something to process a list of name-value pairs in a "stream" and even rolled my own, but then I found this on CPAN.

Axeman
  • 29,660
  • 2
  • 47
  • 102
-1

I don't believe this is possible because Perl is not strongly enough typed to know what subroutines return.

As far as Perl is concerned, all subroutines simply return LISTs (or a single SCALAR). LISTs can have certain operations applied to them (indexing, slicing, etc.), but nothing that requires an ARRAY variable (like push, pop, shift) or a HASH variable (including keys, values, delete, exists).

Hash assignment takes in a LIST as a parameter (which your function returns), and creates an associative hash with every odd element serving as a key to the next even element. Only after this assignment can it be called a HASH in Perl's grammar, and therefore only then will it be usable in the values function.

Platinum Azure
  • 45,269
  • 12
  • 110
  • 134