How can I return a list of hashrefs from a map in Perl?
I have the following code mostly ok:
my $results = { data => [
map {
my $f = $_->TO_JSON;
$f->{display_field} = $_->display_field($q);
$f;
} $rs->all
]};
Only I would prefer it to look like this:
my $results = { data => [ map { %{$_->TO_JSON}, display_field => $_->display_field($q), }, $rs->all ]};
But this gives a syntax error. How can I do what I want, or is my current version the best fit?
update : sorry for the extra semicolon. It's late here. Don't know how I missed it. Thanks guys!
source to share
It only gives a syntax error, because Perl thinks you need to omit the comma after map { ... }
it because it parses this map as a block, not an expression. Place it +
in front, it will fix it. Also, you cannot have a semicolon in an anonymous hash:
my $results = { data => [
map +{
# ^----------------- plus sign added
%{$_->TO_JSON},
display_field => $_->display_field($q);
# ^---- should be comma or nothing
}, $rs->all
]};
source to share
The problem is that Perl doesn't look far ahead to figure out whether {
"run anonymous hash reference" or "run a block of code" means . He should (ideally) look at the appropriate one }
and see if there is a comma or not and act accordingly, but it is not. It looks a little ahead and tries to guess. And this time it's wrong and you get a syntax error about the comma that shouldn't be there, except that it shouldn't move it.
perldoc -f map
will tell you all about it. Basically, it says that if you put it +{
, Perl will understand that it means "not a block of code" and assume it is a hash reference. This is probably the reason for your syntax error. As another suggestion, one might say that map({ HASH STUFF }, $rs->all)
- I'm betting money, Perl won't guess that this is a code link here.
I couldn't get it to work, but without having $rs
either ->TO_JSON
or a variable named $q
, I couldn't get it to work in any way. Hope this helps. If not, write a little more code. Don't worry, we don't bite.
Also, while we're at it, why not write it like this:
my $results;
$results->{data} = [ map MAGIC MAP STUFF, $rs->all ];
It might be more readable, especially if you add a lot of things to $results
everything at once.
source to share
I'm not really sure what kind of structure you are looking for. map
your first example already returns a list of hashrefs (each version $f
).
If you just want the syntax to be similar to your second example, you are almost right; you need to get rid of the extraneous semicolon in your map block and use a couple of curls to make the ref hash anonymous.
Something like:
my $results = { data => [ map { { %{$_->TO_JSON}, display_field => $_->display_field($q) } } $rs->all ]};
source to share