RFC: new API for Type::Params
Firstly, I'm not planning on breaking compatibility with Type::Params. The new API would live under a different namespace, such as Type::Params2.
The API for Type::Params is currently:
use feature 'state'; use Type::Params qw( compile compile_named_oo ); use Types::Standard -types; sub function_with_positional_parameters { state $check = compile( ArrayRef, Int, Int ); my ( $list, $start, $end ) = $check->( @_ ); my @slice = @{$list}[ $start .. $end ]; return \@slice; } sub function_with_named_parameters { state $check = compile_named_oo( list => ArrayRef, start => Int, end => Int ); my ( $arg ) = $check->( @_ ); my @slice = @{$arg->list}[ $arg->start .. $arg->end ]; return \@slice; }
Alternatively, there's:
use Type::Params qw( wrap_subs compile_named_oo ); use Types::Standard -types; wrap_subs function_with_positional_parameters => [ ArrayRef, Int, Int ]; sub function_with_positional_parameters { my ( $list, $start, $end ) = @_; my @slice = @{$list}[ $start .. $end ]; return \@slice; } wrap_subs function_with_named_parameters => compile_named_oo( list => ArrayRef, start => Int, end => Int ); sub function_with_named_parameters { my ( $arg ) = @_; my @slice = @{$arg->list}[ $arg->start .. $arg->end ]; return \@slice; }
My suggested API is:
use feature 'state'; use Type::Params2; use Types::Standard -types; sub function_with_positional_parameters { state $check = signature( pos => [ ArrayRef, Int, Int ], ); my ( $list, $start, $end ) = $check->( @_ ); my @slice = @{$list}[ $start .. $end ]; return \@slice; } sub function_with_named_parameters { state $check = signature( named => [ list => ArrayRef, start => Int, end => Int ], ); my ( $arg ) = $check->( @_ ); my @slice = @{$arg->list}[ $arg->start .. $arg->end ]; return \@slice; }
It would also support the inside-out technique:
use Type::Params2; use Types::Standard -types; signature_for function_with_positional_parameters => ( pos => [ ArrayRef, Int, Int ], ); sub function_with_positional_parameters { my ( $list, $start, $end ) = @_; my @slice = @{$list}[ $start .. $end ]; return \@slice; } signature_for function_with_named_parameters => ( named => [ list => ArrayRef, start => Int, end => Int ], ); sub function_with_named_parameters { my ( $arg ) = @_; my @slice = @{$arg->list}[ $arg->start .. $arg->end ]; return \@slice; }
There would be a shortcut for methods:
signature_for method_with_named_parameters => ( method => 1, named => [ list => ArrayRef, start => Int, end => Int ], ); sub method_with_named_parameters { my ( $self, $arg ) = @_; my @slice = @{$arg->list}[ $arg->start .. $arg->end ]; return \@slice; }
Comments? Do people think this would be an improvement?
TIL
Type::Params
:-)Not having any practical experience with it and referring to just the examples, I feel the second syntax is much cleaner. Certainly, getting rid of
compile_named_oo
is a win.However, I don't think the Perl world needs YetAnotherNumberedModule. Couldn't you just add
signature
andsignature_for
to the current module and let the user do:use Type::Params qw/signature signature_for/;
If you don't want the user to have to use an explicit import, maybe
Type::Signature
would be a good name. Or evenType::ParamsSignature
. Anything butType::Params2
.True.
Or:
My reason for suggesting a different module name is to also be able to simplify documentation for the end users, so the pod for the old stuff they don't need to worry about is away in a different module.
Wouldn’t it be close enough to update the documentation to prominently describe only the new style, and for the old interface just put some stubs near the end of the POD that merely say stuff like (e.g.) this?
That is perhaps the best option.
--modern. I could live with that.
I agree. At the top you can put a blurb like:
Note: This module was given a "facelift" in 2022 with a more natural API. These docs have been revamped to feature the new API prominently, but the old API's functions are still documented within, mapped to the new calls.
I really dislike marketing/judgy terms like “modern” for this kind of thing. “Modern” conveys nothing about the interface, it’s just what someone thinks of it – or rather, thought of it at the time the term was assigned. Next time the API gets a facelift, what then? Postmodern? Hypermodern? What do you put in the documentation, “
-modern
is actually deprecated now”? Or do you – and perish the thought – break backcompat?It’s rather better to use descriptive terms that highlight some defining characteristic of the interface. In this particular case, I’d suggest maybe
-signatures
. That isn’t likely to be invalidated by the next facelift.Expressing an opinion is not per se a problem, but it’s the documentation to which that function belongs, not the interfaces.