Is it possible in Perl to declare a subroutine such that the script won't compile if parameters are not passed to it when it is called?
-
2How can you tell at compile-time if `f(@a)` passes any parameters to `f` or not? – ikegami Oct 11 '17 at 02:41
-
It is in theory possible to do some kind of compile-time checking with Devel::CallChecker or B::CallChecker, but that requires you to be well-versed with Perl internals, and has many failure modes. E.g. it won't work with methods, only with certain subroutine calls. It won't work if any arguments are evaluated in list context. At its core Perl is a dynamic language. Subs process variable-sized lists, not fixed-sized argument tuples. I'm just glad the language is just static enough to detect unknown subs and variables, unlike more dynamic languages like Python. – amon Oct 11 '17 at 07:42
-
What about PPR? – simbabque Oct 11 '17 at 09:48
-
@ikegami I was thinking of `sub func(\@)` (etc) to enforce at compile time the (supposedly intended) calling convention whereby `@ary` is required. Then each sub need be written with its exact "signature" and called only so. So ... that doesn't actually fail your `f(@a)` where `@a` is empty since that sub does get its array while I can't use `@a` to bundle other arguments (that ends up empty at runtime). Is that what you are saying? – zdim Oct 12 '17 at 16:44
-
@ikegami So then prototypes _can_ do this, at the expense of having to write and use _all_ subs like bultins. – zdim Oct 12 '17 at 16:53
-
1@zdim, 1) Well yeah, but prototypes technically don't validate arguments; they change parsing rules. This makes them feel hacky. 2) More importantly, they are sometimes silently ignored. I don't mean when using `&` or a reference or a method call, I mean depending on the relative order of the sub's call and its declaration. 3) The fact that I mostly write OO code means that they are totally useless most of the time. /// That said, we do use them where I work (where the code base is largely procedural), and they have caused less trouble than the problems they have saved. – ikegami Oct 12 '17 at 16:56
-
@ikegami Thank you very much for that summary. I deleted my original comment (half of it was wrong). I've decided to post a note ("answer"), once this got mentioned. – zdim Oct 12 '17 at 19:16
2 Answers
I think this type of thing is about the best you can currently do:
#!/usr/local/bin/perl -w
use strict;
require 5.020;
use warnings;
use feature qw( say signatures );
no warnings "experimental::signatures";
print "Enter your first name: ";
chomp(my $name1 = <STDIN>);
print "Enter your last name: ";
chomp(my $name2 = <STDIN>);
say "Calling takesOneOrTwoScalars with 2 args";
takesOneOrTwoScalars($name1, $name2);
say "Calling takesOneOrTwoScalars with 1 arg";
takesOneOrTwoScalars($name1);
say "Calling takesOneOrTwoScalars with 0 args";
takesOneOrTwoScalars();
sub takesOneOrTwoScalars($firstName, $lastName="")
{
print "Hello, $firstName";
if ($lastName)
{
say " $lastName";
}
else
{
say ", I see you didn't give your last name.";
}
}

- 719
- 4
- 11
-
3Note that this only produces a *runtime error* when an unsuitable argument list is passed. I don't need the signatures feature for that. For example: `use Carp; ... croak "Too few arguments for takesOneOrTwoScalars" if @_ < 1; croak "Too many arguments for takesOneOrTwoScalars" if @_ > 2` – amon Oct 11 '17 at 07:31
Some of that can be achieved with prototypes (persub), to some extent
Perl supports a very limited kind of compile-time argument checking using function prototyping.
...
... intent of this feature is primarily to let you define subroutines that work like built-in functions
For example, subs declared as sub f1(\@)
and sub f2($$)
can only be called as f1(@ary)
(array variable, with @
) and f2(SCALAR, SCALAR)
or there is a compile-time error.
But there is far more to it, with many subtle concerns; please read the docs and the links below. The prototypes are not like function signatures in compiled languages and are not intended to do that job, even though they may appear that way. Even a slight misuse can lead to subtle bugs. See
FMTYEWTK about Prototypes in Perl (perlmonks)
Understand why you probably don't need prototypes (The Effective Perler)
The problem with prototypes (Modern Perl)
All that said, they can be useful if used appropriately. See ikegami's comments under OP.

- 64,580
- 5
- 52
- 81