Most OO languages will allow method overloading based upon signature. Perl does not support this feature. In my latest quest to abuse source filters, I've considered the following:
use Sub::Overload; sub foo() { # do something } sub foo($bar) { # do something else } sub foo($bar, ARRAY $this, ARRAY $that) { # type checking is optional # do something else }
And the source filter will create something like this:
sub _overload_foo_0 { # do something } sub _overload_foo_1SCALAR { my ($bar) = @_; # do something else } sub _overload_foo_1SCALAR_2ARRAY) { my ($foo, $this, $that) = @_; # do something else } sub foo { my %dispatch = ( 0 => \&_overload_foo_0, 1SCALAR => \&_overload_foo_1SCALAR, 1SCALAR2ARRAY => \&_overload_foo_1SCALAR2ARRAY, ); my $signature = Sub::Overload::calculate_signature('foo', @_); unless (exists $dispatch{$signature) { croak("Incorrect $signature for &foo: ($signature)"; } goto $dispatch{$signature}; }
There's a fair amount of work that would have to be done, but if it was done properly, it could conceivably cut down the number of bugs that stem from programmers not checking arguments properly:
sub foo { unless (@_) { goto &_foo; } elsif ( 1 == @_ ) { goto &_foo_with_arg; } else { # possible bug if we fail to check that the second # argument is an array ref goto &_foo_last; } }
goto &some_sub respects wantarray, doesn't it?
And yes, I know about Class::MultiMethods, but the syntax is less natural than what's proposed above. My version will blow line numbers in reporting, though. Putting the variable assignment directly after the opening brace might help and if I install the dispatch sub directly into the symbol table rather than filter the code, that might also help.