Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Sunday December 12, 2004
06:40 PM

Sub::Signatures stumper

[ #22279 ]

I wound up with a serious problem using multi-method dispatch and subroutine signatures. What happens when I hit the following?

use Sub::Signatures 'strict';

sub foo(SomeClass $bar) {
    $bar->bang;
}

sub foo(OtherClass $bar) {
    $bar->bang;
}

If SomeClass and OtherClass are related to one another via inheritance, I have no way of guaranteeing which is related to which at compile time and this complicates dispatching. In Java, this is not a problem because class relationships are set at compile time and cannot change. Thus, this works:

public String foo(Klonk some_var) {
    some_var.wibble();
}

public String foo(SubclassOfKlonk some_var) {
    some_var.wibble();
}

If I call object.foo(anotherObject);, the method dispatch is unambiguous. A bit of research reveals that Class::Multimethods is doing quite a bit of horrifyingly slow work to resolve this issue at runtime and frankly, I may have no choice but to follow along. I've considered, however, a "mixed" mode where one can do this:

use Sub::Signatures 'mixed';

sub foo($bar, $baz, ARRAY $thing) {
    ...
}

sub foo($bar, $baz, Some::Class $thing) {
    ...
}

In this variant, types are ignored unless specified. Then they're required to be an exact match for the variable at hand. Inheritance will not matter. This allows Ruby style "duck typing" for most variables, dispatching on the number of arguments and optional type checking when needed. It also allows this to be conceptually confusing. I'll have to think about this more, but this is discouraging. I have several hours of work today that are now sitting idly on my hard drive.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Time for a probably naïve question can't you simply do something like the following?

    sub decide_type {
        my( $thing, @possible_type ) = @_;

        my %specifity = map {
            $_ => scalar grep isa( $foo, $_ ), @possible_type
        } @possible_type;

        return List::Util::reduce {
            $specifity{ $a } >  $specifity{ $b } ? $a : $b
        } keys %specifity;
    }

    decide_type $foo, qw( Klonk SubclassOfKlonk

    • That's absolutely a naïve question. Of course, I asked the same question. We're both naïve. I assume the isa() function you have returns how many steps away the type is?

      Your solution looks reasonable. I think it can work. Now I have to think about the caching of signatures types and seeing if I can implement that. I don't have much free time during the week, so perhaps next weekend.

      What happens if I declare two functions whose signatures only differ in that one of the parameters must be

      • The isa() function there is just UNIVERSAL::isa(). That's why I'm wondering whether this approach would be too slow were it some custom @ISA walking routine, there'd be no question in the first place. That was the entire point to the code I wrote trying to find the answer to the question which thing out of a hierarchy of possibilities do I have? without walking the inheritance graph manually. I'm pretty sure that invoking UNIVERSAL::isa() ten times, and subsequently implicitly

    • Actually this can be possibly be optimized with a more explicit loop. Once you know that SubclassOfKlonk has a higher specifity than Klonk, you can discard it.

      Obviously that requires more code. Deciding whether the optimization is applicable might be slower than just going about it the brute's way.