shift => '$class',
},
);
+for my $k (keys %type_map) {
+ $type_map{$k . '_strict'} = {
+ %{$type_map{$k}},
+ check_argument_count => 1,
+ };
+}
sub import {
my $class = shift;
The first line creates two keywords, C<proc> and C<meth> (for defining
functions and methods, respectively). The last two lines only create one
keyword. Generally the hash keys (keywords) can be any identifiers you want
-while the values (types) have to be either C<'function'>, C<'method'>,
-C<'classmethod'>, or a hash reference (see below). The main difference between
+while the values (types) have to be either a hash reference (see below) or
+C<'function'>, C<'method'>, C<'classmethod'>, C<'function_strict'>,
+C<'method_strict'>, or C<'classmethod_strict'>. The main difference between
C<'function'> and C<'method'> is that C<'method'>s automatically
L<shift|perlfunc/shift> their first argument into C<$self> (C<'classmethod'>s
are similar but shift into C<$class>).
(These are all default values so C<'function'> is also equivalent to C<{}>.)
+C<'function_strict'> is like C<'function'> but with
+C<< check_argument_count => 1 >>.
+
C<'method'> is equivalent to:
{
shift => '$self',
}
+C<'method_strict'> is like C<'method'> but with
+C<< check_argument_count => 1 >>.
+
C<'classmethod'> is equivalent to:
{
shift => '$class',
}
+C<'classmethod_strict'> is like C<'classmethod'> but with
+C<< check_argument_count => 1 >>.
+
=head2 Syntax and generated code
Normally, Perl subroutines are not in scope in their own body, meaning the
# vvv only if check_argument_count is enabled vvv
Carp::croak "Not enough arguments for fun (anon)" if @_ < 2;
Carp::croak "Too many arguments for fun (anon)" if @_ > 2;
+ # ^^^ ^^^
my ($p, $q) = @_;
...
};
#!perl
-use Test::More tests => 25;
+use Test::More tests => 48;
use warnings FATAL => 'all';
use strict;
is eval('fun foo :() {}; 1'), undef;
like $@, qr/syntax error/;
- pound foo_1($x) { $x }
+ pound foo_1($x, $u) { $x }
is foo_1(2 + 2), 4;
no Function::Parameters qw(pound);
is eval('fun foo () {}; 1'), undef;
like $@, qr/syntax error/;
- pound foo_2() { $self }
+ pound foo_2($u) { $self }
is foo_2(2 + 2), 4;
no Function::Parameters qw(pound);
is eval('fun foo () {}; 1'), undef;
like $@, qr/syntax error/;
- pound foo_3() { $class }
+ pound foo_3($u) { $class }
is foo_3(2 + 2), 4;
no Function::Parameters;
like $@, qr/syntax error/;
}
+{
+ use Function::Parameters { pound => 'function_strict' };
+
+ is eval('fun foo :() {}; 1'), undef;
+ like $@, qr/syntax error/;
+
+ pound foo_4($x) { $x }
+ is foo_4(2 + 2), 4;
+
+ is eval('foo_4(5, 6)'), undef;
+ like $@, qr/Too many arguments/;
+
+ no Function::Parameters qw(pound);
+
+ is eval('pound foo() {}; 1'), undef;
+ like $@, qr/syntax error/;
+}
+
+{
+ use Function::Parameters { pound => 'method_strict' };
+
+ is eval('fun foo () {}; 1'), undef;
+ like $@, qr/syntax error/;
+
+ pound foo_5() { $self }
+ is foo_5(2 + 2), 4;
+
+ is eval('foo_5(5, 6)'), undef;
+ like $@, qr/Too many arguments/;
+
+ no Function::Parameters qw(pound);
+
+ is eval('pound unfoo :() {}; 1'), undef;
+ like $@, qr/syntax error/;
+}
+
+{
+ is eval('pound unfoo( ){}; 1'), undef;
+ like $@, qr/syntax error/;
+
+ use Function::Parameters { pound => 'classmethod_strict' };
+
+ is eval('fun foo () {}; 1'), undef;
+ like $@, qr/syntax error/;
+
+ pound foo_6() { $class }
+ is foo_6(2 + 2), 4;
+
+ is eval('foo_6(5, 6)'), undef;
+ like $@, qr/Too many arguments/;
+
+ no Function::Parameters;
+
+ is eval('pound unfoo :lvalue{}; 1'), undef;
+ like $@, qr/syntax error/;
+}
+
is eval('Function::Parameters->import(":QQQQ"); 1'), undef;
like $@, qr/valid identifier/;