evalEmpire / method-signatures

Method and function declarations with signatures, no source filter
http://metacpan.org/pod/Method::Signatures
Other
33 stars 35 forks source link

`when {}` is a syntax error #60

Closed schwern closed 11 years ago

schwern commented 11 years ago

This works fine.

func foo( $thing = [1,2,3] when [] ) {
    print @$thing
}

This is a messy parse error.

func foo( $thing = { foo => 23 } when {} ) {
    print keys %$thing;
}

Not enough arguments for grep at /Users/schwern/tmp/test.plx line 3, near "} $arg"
syntax error at /Users/schwern/tmp/test.plx line 3, near "} $arg"
syntax error at /Users/schwern/tmp/test.plx line 5, near "}"
Execution of /Users/schwern/tmp/test.plx aborted due to compilation errors.

Something's gone wrong with the injection.

my $thing = !(@_ > 0) ? ( { foo => 23 } ) : do{ no warnings; my $arg = $_[0]; (grep  {} $arg) ? ( { foo => 23 } ) : $arg}; Method::Signatures->too_many_args_error(1) if @_ > 1; 
schwern commented 11 years ago

OIC it thinks its a block. Patch on the way.

schwern commented 11 years ago

Hrm. I can special case an empty hash, but what about hashes in general? I don't think there will be much call for checking for anything but an empty hash, so I'm inclined to just special case it. Anything more complicated can be done as a full block.

thoughtstream commented 11 years ago

Hashes in general are already supported.

PPI uses the usual perlish guesswork to determine whether a pair of curlies are a hash or a block.

Empty curlies are arguably a useless special case as an empty hash will never smartmatch anything.

Of course, treating {} as an empty block would be equally useless, so special casing them as empty hash is probably for the best (i.e. least surprising).

barefootcoder commented 11 years ago

Well, we should probably special-case it as whatever-doesn't-generate-a-syntax-error. :-D

This fix will go into the next dev release. Just waiting now for CPANTesters to throw up some reports for me to look at ...

schwern commented 11 years ago

@thoughtstream PPI might have that guesswork, but inject_for_sig() isn't using it. It's using a regex. I'll look at switching it to PPI, but this fix to the existing regex should go in.

And an empty hash ref smart matches, surprise, an empty hash ref.

perl -wle '$h = {};  print $h ~~ {} ? "Match" : "No Match" '
Match

perl -wle '$h = { foo => 23 };  print $h ~~ {} ? "Match" : "No Match" '
No Match

This is handy for providing a default if the user passes in an empty hash ref, similar to using when "" for a string parameter.

thoughtstream commented 11 years ago

Very good point re empty hashref matching empty hashes. This definitely should be special-cased.

barefootcoder commented 11 years ago

Fixed in version 20121201.