Skip Menu |

This queue is for tickets about the MooseX-Params-Validate CPAN distribution.

Report information
The Basics
Id: 106192
Status: new
Priority: 0/
Queue: MooseX-Params-Validate

People
Owner: Nobody in particular
Requestors: KENTNL [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.21
Fixed in: (no value)



Subject: Not usable on functions or class methods

Class Methods and Functions are effectively unusable with MX:PV

With a class method, defacto passing \@_ causes the "Get object at first and assume its self" heuristic to fail, and so it sees the class name ( a string ) and assumes its the key for a parameter, causing "odd number of elements in hash assignment"

( See class_method.pl )

Working around this defect by explicitly shifting of $class first ( the same as Params::Validate expects ), results in a secondary defect:  That if somebody passes an object as the first parameter to the class method, then that will be assumed to be "self" of a method call, changing how the returned values occur silently without exceptions, instead of rejecting the parameters as invalid

( see class_method_2.pl )

And this second case exhibits its ugly head when used for functions also, that if the first argument happens to be any kind of object, it will assume its an invocant, even if the functions definition anticipated no such thing.

( see function.pl )

As such, I would request one of two possible options:

 

1. Have documentation to effect of stating clearly that it is not useful for functions and class methods due to permitting invalid argument lists in certain conditions.

2. Have a parameter that disables the "assume an invocant if $_[0] is a bless" mechanics.

I think the second of these two would be more useful, and then that flag would be turned on
and the "shift" be manually done for class methods, and no other magic required for functions.

An additional set of options may also prove useful:

1. A "require invocant" flag that stipulates $_[0] **must** be a bless and errors otherwise.

2. An "assume invocant" flag that stipulates $_[0] is **always** assumed to be an invocant ( either class name or bless ), instead of magically doing it when $_[0] is a bless.

The first of these options would cause exceptions when a method is erroneously called as a function, instead of having the parameters silently get stuffed into the wrong boxes.

The second of these would be useful for methods that worked on either objects or classes, as "$self" would be predictably always present in the right place in the output, and the remaining args would have well defined even-numbered list semantics, and so:

Test->class_method( $object => "x" )

Would always be assumed to parse such that "Test" is the invocant, and "$object" is merely the first key, which is entirely realistic in the event $object is a stringifiable object that mimics a string, like a Path::Tiny instance.

 

Subject: class_method.pl
#!/usr/bin/env perl # ABSTRACT: test class methods use strict; use warnings; package Test { use MooseX::Params::Validate qw( validated_list ); sub class_method { my ( $class, $arg_one ) = validated_list( \@_, arg_one => { isa => 'Object' } ); print "class is $class"; } } Test->class_method( arg_one => bless({}, 'X' ) );
Subject: class_method_2.pl
#!/usr/bin/env perl # ABSTRACT: test class methods use strict; use warnings; package Test { use MooseX::Params::Validate qw( validated_list ); sub class_method { my ( $class, @args ) = @_; my ( $arg_one, $arg_two ) = validated_list( \@args, arg_one => { isa => 'Object' } ); print "class is $class\n"; print "arg_one is $arg_one\n"; print "arg_two is $arg_two\n" if $arg_two; } } print "#1\n"; Test->class_method( arg_one => bless({}, 'X' ) ); print "#2\n"; Test->class_method( bless({}, 'Y' ), arg_one => bless({}, 'X' ) );
Subject: function.pl
#!/usr/bin/env perl # ABSTRACT: test functions use strict; use warnings; package Test { use MooseX::Params::Validate qw( validated_list ); sub function { my ( $arg_one, $arg_two ) = validated_list( \@_, arg_one => { isa => 'Object' } ); print "arg_one is $arg_one\n"; print "arg_two is $arg_two\n" if $arg_two; } } print "#1\n"; Test::function( arg_one => bless({}, 'X' ) ); print "#2\n"; Test::function( bless({}, 'Y' ), arg_one => bless({}, 'X' ) );