Question

In adding a TO_JSON method (to convert a blessed reference via JSON.pm) into CGI::Cookie if I do this:

package CGI::Cookie;
sub TO_JSON {
    return {
        map { name => $_->name,
              value => $_->value,
              domain => $_->domain,
              path => $_->path,
              expires => $_->expires }
            shift
    }
}

syntax error at XXX.pm line 76, near "shift " syntax error at XXX.pm line 77, near "}" Compilation failed in require at (eval 50) line 3.

But if I do this:

package CGI::Cookie;
sub TO_JSON {
    return {
        map { ''.'name' => $_->name,
              value => $_->value,
              domain => $_->domain,
              path => $_->path,
              expires => $_->expires }
            shift
    }
}

it works

Can't for the life of me figure out why. Also just quoting "name" doesn't help. I have to concatenate an empty string for it to work.

I'm mystified.

Was it helpful?

Solution

The Perl grammar is a bit ambiguous when it comes to blocks and anonymous hashrefs. When Perl cannot guess correctly, you can force the correct interpretation:

  • Hashref by +{ ... }
  • Codeblock by {; ... }

Forcing the block after map to be a codeblock resolves the issue. Previously it thought the block was an anonymous hash, and missed a comma before the shift: map can be of the form map EXPR, LIST, and a hashref is a valid expression.


The sub uses misuses map to assign one element to $_. It would better be written:

sub TO_JSON {
    my $o = shift; # my $_ should work as well, but that is beside the point
    return +{
       name    => $o->name,
       value   => $o->value,
       domain  => $o->domain,
       path    => $o->path,
       expires => $o->expires,
    };
}

But it could be abbreviated to

sub TO_JSON {
    my $o = shift;
    return +{
       map { $_ => $o->$_() } qw/name value domain path expires/
    };
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top