.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.0102 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Sub::HandlesVia::Manual::Advanced 3" .TH Sub::HandlesVia::Manual::Advanced 3 2024-09-02 "perl v5.40.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Sub::HandlesVia::Manual::Advanced \- misc advanced documentation .SH MANUAL .IX Header "MANUAL" The following information applies no matter which OO toolkit you are using. .SS "Method Chaining" .IX Subsection "Method Chaining" Say you have the following .PP .Vb 6 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqadd_food\*(Aq => \*(Aqpush\*(Aq, \& \*(Aqfind_food\*(Aq => \*(Aqgrep\*(Aq, \& \*(Aqremove_food\*(Aq => \*(Aqpop\*(Aq, \& }, .Ve .PP Now \f(CW\*(C`$kitchen\->remove_food\*(C'\fR will remove the last food on the list and return it. But what if we don't care about what food was removed? We just want to remove the food and discard it. You can do this: .PP .Vb 6 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqadd_food\*(Aq => \*(Aqpush\*(Aq, \& \*(Aqfind_food\*(Aq => \*(Aqgrep\*(Aq, \& \*(Aqremove_food\*(Aq => \*(Aqpop...\*(Aq, \& }, .Ve .PP Now the \f(CW\*(C`remove_food\*(C'\fR method will return the kitchen object instead of returning the food. This makes it suitable for chaining method calls: .PP .Vb 2 \& # remove the three most recent foods \& $kitchen\->remove_food\->remove_food\->remove_food; .Ve .SS "Delegating to CodeRefs" .IX Subsection "Delegating to CodeRefs" You can delegate to coderefs: .PP .Vb 4 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqfind_healthiest\*(Aq => sub { my $foods = shift; ... }, \& } .Ve .SS "Delegating to Named Methods" .IX Subsection "Delegating to Named Methods" The Sub::HandlesVia::HandlerLibrary::Blessed handler library allows you to delegate to named methods of a blessed object. .PP .Vb 6 \& isa => InstanceOf[\*(AqHTTP::Tiny\*(Aq], \& handles_via => \*(AqBlessed\*(Aq, \& handles => { \& \*(Aqhttp_get\*(Aq => \*(Aqget\*(Aq, \& \*(Aqhttp_post\*(Aq => \*(Aqpost\*(Aq, \& }, .Ve .PP However, in Moo, Moose, Mouse, and Mite, this kind of delegation is baked in, so you don't even need Sub::HandlesVia! .PP .Vb 5 \& isa => InstanceOf[\*(AqHTTP::Tiny\*(Aq], \& handles => { \& \*(Aqhttp_get\*(Aq => \*(Aqget\*(Aq, \& \*(Aqhttp_post\*(Aq => \*(Aqpost\*(Aq, \& }, .Ve .PP Still, the Sub::HandlesVia::HandlerLibrary::Blessed handler library may still be useful if you wish to use other Sub::HandlesVia features like chaining, or if you're using a different OO toolkit. .PP 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. .PP .Vb 6 \& isa => InstanceOf[\*(AqFoodList\*(Aq], \& handles_via => \*(AqArray\*(Aq, \*(AqBlessed\*(Aq, \& handles => { \& \*(Aqfind_food\*(Aq => \*(Aqgrep\*(Aq, \& \*(Aqfind_healthiest_food\*(Aq => \*(Aqfind_healthiest\*(Aq, \& }, .Ve .PP Now \f(CW\*(C`$kitchen\->find_food($coderef)\*(C'\fR does this (which breaks encapsulation ): .PP .Vb 1 \& my @result = grep $coderef\->(), @{ $kitchen\->food }; .Ve .PP But because \f(CW\*(C`find_healthiest\*(C'\fR 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 \&\f(CW\*(C`$kitchen\->find_healthiest_food\*(C'\fR does this: .PP .Vb 1 \& $kitchen\->food\->find_healthiest .Ve .PP It can be useful to be explicit about which methods you wish to delegate to a "native trait" style array and which are named methods to be called on a blessed object: .PP .Vb 6 \& isa => InstanceOf[\*(AqFoodList\*(Aq], \& handles_via => [ \*(AqArray\*(Aq, \*(AqBlessed\*(Aq ], \& handles => { \& \*(Aqfind_food\*(Aq => \*(AqArray\->grep\*(Aq, \& \*(Aqfind_healthiest_food\*(Aq => \*(AqBlessed\->find_healthiest\*(Aq, \& }, .Ve .PP See "Delegating to Multiple Handler Libraries". .SS "Curried Arguments" .IX Subsection "Curried Arguments" All this talk of food is making me hungry, but as much as I'd like to eat a curry right now, that's not the kind of currying we're talking about. .PP .Vb 4 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqget_food\*(Aq => \*(Aqget\*(Aq, \& }, .Ve .PP \&\f(CW\*(C`$kitchen\->get_food(0)\*(C'\fR will return the first item on the list. \&\f(CW\*(C`$kitchen\->get_food(1)\*(C'\fR will return the second item on the list. And so on. .PP .Vb 5 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqfirst_food\*(Aq => [ \*(Aqget\*(Aq => 0 ], \& \*(Aqsecond_food\*(Aq => [ \*(Aqget\*(Aq => 1 ], \& }, .Ve .PP I think you already know what this does. Right? .PP And yes, currying works with coderefs. .PP .Vb 4 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqblargy\*(Aq => [ sub { ... }, @curried ], \& }, .Ve .SS "Looser Argument Checking" .IX Subsection "Looser Argument Checking" Sub::HandlesVia tries to be strict by default. For example, if your attribute specifies \f(CW\*(C`isa => ArrayRef[Int]\*(C'\fR then your method which delegates to \&\f(CW\*(C`push\*(C'\fR will check that its arguments are integers. .PP You can tell it to be less rigourous checking method arguments using the \&\f(CW\*(C`~\*(C'\fR prefix: .PP .Vb 4 \& handles_via => \*(AqArray\*(Aq, \& handles => { \& \*(Aqfind_food\*(Aq => \*(Aq~grep\*(Aq, \& }, .Ve .SS "Delegating to Multiple Handler Libraries" .IX Subsection "Delegating to Multiple Handler Libraries" Sometimes you may wish to pick methods to delegate to from multiple handler libraries. This is possible by setting \f(CW\*(C`handles_via\*(C'\fR to an arrayref. .PP .Vb 6 \& isa => ArrayRef|HashRef, \& handles_via => [ \*(AqArray\*(Aq, \*(AqHash\*(Aq ], \& handles => { \& the_keys => \*(Aqkeys\*(Aq, \& ship_shape => \*(Aqsort_in_place\*(Aq, \& } .Ve .PP Here you have an attribute which might be an arrayref or a hashref. When it's an arrayref, \f(CW\*(C`$object\->ship_shape\*(C'\fR will work nicely, but \f(CW\*(C`$object\->the_keys\*(C'\fR will fail badly. .PP Still, this sort of thing \fIcan\fR kind of make sense if you have an object that overloads both \f(CW\*(C`@{}\*(C'\fR and \f(CW\*(C`%{}\*(C'\fR. .PP 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, are all scalars. .PP Sometimes a method name will be ambiguous. For example, there's a \&\f(CW\*(C`get\*(C'\fR method for both hashes and arrays. In this case, the array one will win because you listed it first in \f(CW\*(C`handles_via\*(C'\fR. .PP But you can be specific: .PP .Vb 6 \& isa => ArrayRef|HashRef, \& handles_via => [ \*(AqArray\*(Aq, \*(AqHash\*(Aq ], \& handles => { \& get_by_index => \*(AqArray\->get\*(Aq, \& get_by_key => \*(AqHash\->get\*(Aq, \& } .Ve .SH BUGS .IX Header "BUGS" Please report any bugs to . .SH "SEE ALSO" .IX Header "SEE ALSO" Sub::HandlesVia. .SH AUTHOR .IX Header "AUTHOR" Toby Inkster . .SH "COPYRIGHT AND LICENCE" .IX Header "COPYRIGHT AND LICENCE" This software is copyright (c) 2022 by Toby Inkster. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. .SH "DISCLAIMER OF WARRANTIES" .IX Header "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.