Question

I have the following mostly ok code:

my $results = { data => [
   map {
      my $f = $_->TO_JSON;
      $f->{display_field} = $_->display_field($q);
      $f;
   } $rs->all
]};

Only I'd rather it were more like the following:

my $results = { data => [
   map {
      %{$_->TO_JSON},
      display_field => $_->display_field($q),
   }, $rs->all
]};

But that gives a syntax error. How can I do what I want, or is my current version the best it gets?

update: sorry about the extra semicolon from before. It's late here. Not sure how I missed it. Thanks guys!

Was it helpful?

Solution

It only gives a syntax error because you Perl thinks you need to omit the comma after map { ... }, because it is parsing that map as being a block, not an expression. Putting + in front will fix that. Also, you can't 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
]};

OTHER TIPS

The problem is that Perl doesn't look ahead far enough to figure out whether { means "start an anonymous hash reference" or "start a code block". It should (ideally) look to the corresponding } and see if there is or isn't a comma, and act accordingly, but it doesn't. It only looks a little bit ahead and tries to guess. And this time it's wrong, and you get a syntax error about a comma that shouldn't be there, except that it should so don't move it.

perldoc -f map will tell you all about this. Basically, it says that if you put +{, Perl will understand that this means "not a code block" and guess that it's a hash reference. This is probably the cause of your syntax error. As another suggestion, it might work to say map({ HASH STUFF }, $rs->all) - I bet money Perl won't guess it's a code reference here.

I couldn't get it to work, but not having $rs or a ->TO_JSON or a variable named $q I couldn't get any of this to work anyway. I hope this helps. If not, post a little more code. Don't worry, we don't bite.

Also, while we're at it, why not write it this way:

my $results;
$results->{data} = [ map MAGIC MAP STUFF, $rs->all ];

Might arguably be more readable, especially if you're adding a lot of stuff to $results all at once.

I'm not completely sure what kind of structure you're looking for. The map in your first example already returns a list of hashrefs (every version of $f).

If you just want syntax similar to your second example, then you were almost right; you need to get rid of the extraneous semicolon in your map block, and use a pair of curlies to make an anonymous hash ref.

Something like:

my $results = { data => [
    map { { %{$_->TO_JSON},
            display_field => $_->display_field($q)
          }
    } $rs->all
]};

I just always use map in the block form, and structure the code so it's easy to pick apart. Although you can put a + in front of the opening curly to use the expression form, does it really matter to you that much?

Aside from everything else going on, your first example looks fine. Move on and solve real problems. :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top