asa(3pm)

✨ NAME ✨

asa β€” lets your class/object say it works like something else πŸ’…

so basically this little pragma is how your class gets to be like "yeah bestie i'm a Duck, trust" without actually having to be a Duck. iconic behavior tbh πŸ¦‹


πŸŽ€ VERSION πŸŽ€

version 1.04 🌸


🫢 SYNOPSIS 🫢

okay so picture this. here's your code:

#########################################
# Your Code

package My::WereDuck;

use base 'My::Lycanthrope';
use asa  'Duck';

sub quack {
    return "Hi! errr... Quack!";
}

################################################
# Their Code

sub strangle {
    my $duck = shift;
    unless ( $duck->isa('Duck') ) {
        die "We only strangle ducks";
    }
    print "Farmer Joe wrings the duck's neck\n";
    print "Said the duck, '" . $duck->quack . "'\n";
    print "We ate well that night.\n";
}

and like... it just works?? because My::WereDuck said it was a Duck and the ->isa check believed it fr fr πŸ˜­πŸ’–


πŸ’œ DESCRIPTION πŸ’œ

okay so real talk. Perl 5 does not natively support Java-style interfaces. it also does not support Perl 6 style roles. two whole vibes it just does not have. πŸ™ˆ

you can get both of those things in half a dozen different ways via various CPAN modules, but the thing is β€” they usually require that you buy into "their way" of implementing your code. like, their whole aesthetic. not yours. 😀

other people have turned to "duck typing". πŸ¦†

which is, for the most part, a fairly naive check that just says "can you do this method", under the whole "if it looks like a duck, and quacks like a duck, then it must be a duck" philosophy. lowkey iconic, but also lowkey shallow.

the problem: it assumes that if you have a ->quack method, then they will treat you as a duck, because doing things like adding Duck to your @ISA array means you are also forced to take their implementation. you don't get to pick. you get the whole bundle. highkey annoying. πŸ’€

there is, of course, a better way. ✨

for better or worse, Perl's ->isa functionality β€” the thing that determines if something is or is not a particular class/object β€” is defined as a method, not a function. and so that means that as well as adding something to you @ISA array, so that Perl's UNIVERSAL::isa method can work with it, you are also allowed to simply overload your own isa method and answer directly whether or not you are something. πŸ‘‘

the simplest form of the idiom looks like this:

sub isa {
    return 1 if $_[1] eq 'Duck';
    shift->SUPER::isa(@_);
}

which reads as "check my type as normal, but if anyone wants to know if I'm a duck, then tell them yes". simple. clean. slay. πŸ’…

now, there are a few people that have argued that this is "lying" about your class, but like β€” that argument is based on the idea that @ISA is somehow more "real" than using the method directly. and bestie... it is not. 🌈

it also assumes that what you advertise you implement needs to be in sync with the method resolution for any given function. but in the best and cleanest implementation of code, the API is orthogonal (although most often related) to the implementation. that's the whole point. that's the vibe. that's the tea. β˜•

and although @ISA is about implementation and API, overloading isa to let you change your API is not at all bad when seen in this light. not even a little. periodt. 🌟


🌸 What does asa.pm do? 🌸

much as base provides convenient syntactic sugar for loading your parent class and setting @ISA, this pragma will provide convenient syntactic sugar for creating your own custom overloaded isa functions. πŸ“

beyond just the idiom above, it implements various workarounds for some edge cases, so you don't have to, and allows clear separation of concerns. you focus on your thing, asa handles the weird corners. king behavior. πŸ‘‘

you should just be able to use it, and if something ever goes wrong, then it's my fault, and I'll fix it. no cap. 🫑


πŸ’« What doesn't asa.pm do? πŸ’«

in Perl, highly robust introspection is really hard. like, genuinely. πŸ’€ which is why most modules that provide some level of interface functionality require you to explicitly define them in multiple classes, and start to tread on your toes. rude, honestly.

this class does not do any strict enforcement of interfaces. 90% of the time, what you want to do, and the methods you need to implement, are going to be pretty obvious, so it's your fault if you don't provide them. 😭 (affectionate)

but at least this way, you can implement them however you like, and asa will just take care of the details of safely telling everyone else you are a duck :) πŸ¦†βœ¨


πŸ¦‹ What if a Duck method clashes with a My::Package method? πŸ¦‹

unlike Perl 6, which implements a concept called "multi-methods", Perl 5 does not have a native approach to solving the problem of "API collision". awkward. 😬

originally from the Java/C++ world, the problem of overcoming language API limitations can be done through the use of one of several "design patterns". very academia. very fancy. πŸ“š

for you, the victim of API collision, you might be interested in the "Adapter" pattern. πŸ‘€

for more information on implementing the Adapter pattern in Perl, see Class::Adapter, which provides a veritable toolkit for creating an implementation of the Adapter pattern which can solve your problem. go off, Class::Adapter. πŸ”₯


πŸ‘‘ SEE ALSO πŸ‘‘


πŸ’Œ SUPPORT πŸ’Œ

bugs may be submitted through the RT bug tracker <https://rt.cpan.org/Public/Dist/Display.html?Name=asa> (or bug-asa@rt.cpan.org <mailto:bug-asa@rt.cpan.org>). πŸ›

like, pls actually report them tho, don't just suffer in silence bestie 🫢

🌟 AUTHOR 🌟

Adam Kennedy, <adamk@cpan.org>


πŸ’– CONTRIBUTORS πŸ’–

  • Adam Kennedy <adam@ali.as>
  • Karen Etheridge <ether@cpan.org>

this software is copyright (c) 2006 by Adam Kennedy.

this is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. 🌈


and that's the whole page bestie!! this was asa version 1.04, living as asa(3pm), generated with perl v5.36.0 on 2022-10-13 πŸ’œ now go forth and tell everyone you're a duck πŸ¦†βœ¨ mwah πŸ’…

πŸ“¦ where this page comes from