Sub::Ha...Advanced(3)

πŸ’– Sub::Ha...Advanced πŸ’–

okay bestie, welcome to the Sub::HandlesVia::Manual::Advanced page β€” yes that's the manual name, it's from User Contributed Perl Documentation, and it's the "misc advanced documentation" drop. ✨

🌸 NAME 🌸

Sub::HandlesVia::Manual::Advanced β€” misc advanced documentation, fr fr.


πŸŽ€ MANUAL πŸŽ€

Everything below? Applies no matter which OO toolkit you're using. Universal. Iconic. Let's go. πŸ’…

πŸ¦‹ Method Chaining πŸ¦‹

okay so imagine you've got this:

     handles_via => 'Array',
     handles     => {
       'add_food'    => 'push',
       'find_food'   => 'grep',
       'remove_food' => 'pop',
     },

So $kitchen->remove_food pops the last food off the list and returns it. Cute. But bestie… what if you literally do not care what food got removed? You just want it gone. Discarded. Not in your mentions. πŸ—‘οΈ

Then you do this:

     handles_via => 'Array',
     handles     => {
       'add_food'    => 'push',
       'find_food'   => 'grep',
       'remove_food' => 'pop...',
     },

Notice the ...? That's the moment. Now remove_food returns the kitchen object instead of the food, which makes it perfect for chaining method calls:

# remove the three most recent foods
$kitchen->remove_food->remove_food->remove_food;

three in a row, no cap. that's the vibe. πŸ”₯

🧚 Delegating to CodeRefs 🧚

You can delegate to coderefs, periodt:

     handles_via => 'Array',
     handles    => {
       'find_healthiest' => sub { my $foods = shift; ... },
     }

πŸ‘‘ Delegating to Named Methods πŸ‘‘

The Sub::HandlesVia::HandlerLibrary::Blessed handler library lets you delegate to named methods of a blessed object. ✨

     isa         => InstanceOf['HTTP::Tiny'],
     handles_via => 'Blessed',
     handles     => {
       'http_get'   => 'get',
       'http_post'  => 'post',
     },

But hold on β€” in Moo, Moose, Mouse, and Mite, this kind of delegation is baked in, so you don't even need Sub::HandlesVia! 😭

     isa         => InstanceOf['HTTP::Tiny'],
     handles     => {
       'http_get'   => 'get',
       'http_post'  => 'post',
     },

That said, the Sub::HandlesVia::HandlerLibrary::Blessed handler library can still be useful if you want other Sub::HandlesVia features like chaining, or if you're rolling with a different OO toolkit. options, bestie. always options. 🫢

Now, an example of combining delegation to named methods with "native trait" style delegation… let's say FoodList is a class where instances are blessed arrayrefs of strings.

     isa         => InstanceOf['FoodList'],
     handles_via => 'Array', 'Blessed',
     handles     => {
       'find_food'             => 'grep',
       'find_healthiest_food'  => 'find_healthiest',
     },

So now $kitchen->find_food($coderef) does this β€” and heads up, this breaks encapsulation πŸ™ˆ:

my @result = grep $coderef->(), @{ $kitchen->food };

But because find_healthiest isn't one of the methods offered by Sub::HandlesVia::HandlerList::Array, Sub::HandlesVia assumes you want to call it on the arrayref like a proper method, so $kitchen->find_healthiest_food does this instead:

$kitchen->food->find_healthiest

It can be genuinely useful to be explicit about which methods you're delegating to a "native trait" style array, and which ones are named methods called on a blessed object:

     isa         => InstanceOf['FoodList'],
     handles_via => [ 'Array', 'Blessed' ],
     handles     => {
       'find_food'             => 'Array->grep',
       'find_healthiest_food'  => 'Blessed->find_healthiest',
     },

See "Delegating to Multiple Handler Libraries" below. πŸ’–

πŸ“ Curried Arguments πŸ“

All this food talk is making me hungry, but as much as I'd love a curry right now, that is not the kind of currying we're talking about. 😭

     handles_via => 'Array',
     handles     => {
       'get_food'   => 'get',
     },

$kitchen->get_food(0) returns the first item on the list. $kitchen->get_food(1) returns the second. and so on, and so on, iykyk. ⭐

     handles_via => 'Array',
     handles     => {
       'first_food'   => [ 'get' => 0 ],
       'second_food'  => [ 'get' => 1 ],
     },

I think you already know what this does. Right? πŸ’…

And yes β€” currying works with coderefs too.

     handles_via => 'Array',
     handles     => {
       'blargy'       => [ sub { ... }, @curried ],
     },

πŸ’œ Looser Argument Checking πŸ’œ

Sub::HandlesVia tries to be strict by default. For example, if your attribute specifies isa => ArrayRef[Int] then your method that delegates to push will check that its arguments are integers. rigorous queen. πŸ‘‘

You can tell it to be less rigourous about checking method arguments using the ~ prefix:

     handles_via => 'Array',
     handles     => {
       'find_food'   => '~grep',
     },

🌈 Delegating to Multiple Handler Libraries 🌈

Sometimes you wanna pick methods to delegate to from multiple handler libraries. Totally possible β€” just set handles_via to an arrayref. πŸŽ€

   isa         => ArrayRef|HashRef,
   handles_via => [ 'Array', 'Hash' ],
   handles     => {
     the_keys     => 'keys',
     ship_shape   => 'sort_in_place',
   }

So here you have an attribute that might be an arrayref or a hashref. When it's an arrayref, $object->ship_shape will work nicely, but $object->the_keys will fail badly. πŸ’€

Still, this sort of thing can kind of make sense if you have an object that overloads both @{} and %{}. slay, honestly.

In particular, the Sub::HandlesVia::HandlerLibrary::Scalar library often makes sense to combine with the other libraries, because strings, integers, numbers, booleans, and even arrayrefs, hashrefs, and coderefs β€” they're all scalars. ✨

Sometimes a method name will be ambiguous. For example, there's a get method for both hashes and arrays. In this case, the array one wins, because you listed it first in handles_via.

But you can be specific:

     isa         => ArrayRef|HashRef,
     handles_via => [ 'Array', 'Hash' ],
     handles     => {
       get_by_index => 'Array->get',
       get_by_key   => 'Hash->get',
     }

πŸ› BUGS πŸ›

Please report any bugs to <https://github.com/tobyink/p5-sub-handlesvia/issues>. do it bestie, they wanna hear from you πŸ’–


πŸ‘€ SEE ALSO πŸ‘€

Sub::HandlesVia.


🌸 AUTHOR 🌸

Toby Inkster <tobyink@cpan.org>.


This software is copyright (c) 2022 by Toby Inkster.

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


⚠️ DISCLAIMER OF WARRANTIES ⚠️

THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

and that's the whole thing, bestie!! πŸŽ€βœ¨ this was Sub::Ha...Advanced(3), from perl v5.42.0, dated 2026-02-11 β€” go forth and delegate responsibly πŸ’…πŸ’–πŸ¦‹

πŸ“¦ where this page comes from