1

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.

1 Answer 1

2

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/
    };
}
1
  • Thanks. Very weird though since a codeblock is supposed to be the preferred first argument to map(), I would think that would be the first thing that Perl would assume. This works as well: package CGI::Cookie; sub TO_JSON { return { map {;name => $_->name, value => $_->value, domain => $_->domain, path => $_->path, expires => $_->expires } shift } }
    – Rex Dexter
    Commented Apr 18, 2013 at 20:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.