mauke / Function-Parameters

Function::Parameters - define functions and methods with parameter lists ("subroutine signatures")
https://metacpan.org/pod/Function::Parameters
18 stars 19 forks source link

Method::Signatures support #8

Closed schwern closed 1 year ago

schwern commented 9 years ago

I just came across this module and it basically solves the architectural problems with Method::Signatures. I think it's superior and would like to make a fully compatible wrapper. There's some missing syntax needed to bridge the gap.

These are the easy ones.

These are the not so easy ones (and fortunately pretty rarely used)

It would be great if there were options to turn these on. The C parts are beyond my abilities, but if the easy ones were added I could write a compatibility wrapper between Method::Signatures and Function::Parameters.

mauke commented 9 years ago

Heh, well ...

Those are pretty much the syntax/features I deliberately didn't implement because I don't like them.

  • $foo? equivalent to $foo=

FWIW, I don't like the idea of "optional" parameters in general. You (as in "the programmer") should specify what happens if an argument is missing, via default arguments. My gut feeling is that this leads to better code than ? and checking for undef in the body.

I did implement $foo = as shorthand for $foo = undef because the core perl feature allows it. I realize there's no real difference to ? but it still feels better to me somehow.

  • Named parameters are optional (unless made required with !)

Why? I think this idea originates from Perl6 but what's the rationale here?

  • $foo! ($foo is required)

See above. You don't even need this flag if parameters are required by default, which I think is a much simpler rule to remember.

  • ... (ignores the rest of the arguments)
  • @_ (ignores the rest of the arguments)

I think it makes for more readable code if unused parameters are still given names (possibly with a _ or similar prefix to mark them as unused), so I would have made you write @_rest or similar. But now we have core syntax for this (bare @), so that's what I implemented.

Besides, if you write ($x, $y, @_), would @_ in the function still contain $x and $y? If so, that's rather misleading. (If not, @_ does more than just ignore arguments: it also has to shift off the preceding parameters.)

  • func foo is equivalent to fun foo()

This is an option I don't have issues with, especially now that we have fun foo(@) to get the old behavior.


The not so easy ones are stuff I thought was hard to implement for little or no gain.

That said, I'll look into the easy ones and maybe implement them as non-default options, because despite my moral objections, I think it would make F:P more useful as a backend module.

schwern commented 9 years ago

I agree that Function::Parameters does it better, and its better aligned with Perl 5, and it's configurable. The rationale here is they're for compatibility so Method::Signatures users can switch away from Devel::Declare without someone having to redo all your work or M::S users having to rewrite all their signatures. I really would like to be able to dump the Method::Signatures code base. I know ? and ! are redundant, but they're really commonly used. Not implementing them as options would cripple the wrapper.

To explain the Method::Signatures syntax (I'm not advocating it), it follows the Perl 6 signature syntax (as it existed at the time, I have no idea where it's gone). That's where ? and ! come from. ? is redundant with = and isn't necessary, but $foo= wasn't there yet to fully replace it. ! is necessary because named parameters are optional by default. @_ was made up by me, and Buddy and/or Damian came up with ... all before bare $, @, and % came along.

is came along to allow more obscure attributes without having to make up more syntax. when is a generalization of =. You'll have to ask Damien about where. Like I said, those are pretty obscure and easy for the M::S user to change so they don't need to be supported.

I have a handful of ideas I do want to carry over from M::S, I'll raise them as separate issues.

PS The pluggable type system worked like a charm! reify_type => sub { Method::Signatures->_make_constraint($_[0]) },. F::P does cache that result at compile time, right?

schwern commented 9 years ago

PS I forgot about //= for compatibility. I added it to the original post.

mauke commented 9 years ago

PS The pluggable type system worked like a charm! reify_type => sub { Method::Signatures->_make_constraint($_[0]) },.

Good to know. :-)

F::P does cache that result at compile time, right?

Well, kind of. It calls reify_type at compile time and puts the returned object in the generated code - as an object literal, something Perl doesn't normally have, which is why B::Deparse output looks funny. :-)

This avoids runtime type lookup, but reify_type isn't memoized: fun foo(Int $x, Int $y) will call reify_type twice (of course you can always add a cache in reify_type yourself if you need that).

schwern commented 9 years ago

That's the sort of caching I was asking about, great!

aaronpriven commented 8 years ago

Could aliasing now be implemented using the experimental refalias feature of Perl 5.22?