summaryrefslogtreecommitdiffstats
path: root/upstream/debian-unstable/man3/autodie::hints.3perl
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/debian-unstable/man3/autodie::hints.3perl')
-rw-r--r--upstream/debian-unstable/man3/autodie::hints.3perl413
1 files changed, 413 insertions, 0 deletions
diff --git a/upstream/debian-unstable/man3/autodie::hints.3perl b/upstream/debian-unstable/man3/autodie::hints.3perl
new file mode 100644
index 00000000..eef4531f
--- /dev/null
+++ b/upstream/debian-unstable/man3/autodie::hints.3perl
@@ -0,0 +1,413 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43)
+.\"
+.\" 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 "autodie::hints 3perl"
+.TH autodie::hints 3perl 2024-01-12 "perl v5.38.2" "Perl Programmers Reference Guide"
+.\" 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
+autodie::hints \- Provide hints about user subroutines to autodie
+.SH SYNOPSIS
+.IX Header "SYNOPSIS"
+.Vb 1
+\& package Your::Module;
+\&
+\& our %DOES = ( \*(Aqautodie::hints::provider\*(Aq => 1 );
+\&
+\& sub AUTODIE_HINTS {
+\& return {
+\& foo => { scalar => HINTS, list => SOME_HINTS },
+\& bar => { scalar => HINTS, list => MORE_HINTS },
+\& }
+\& }
+\&
+\& # Later, in your main program...
+\&
+\& use Your::Module qw(foo bar);
+\& use autodie qw(:default foo bar);
+\&
+\& foo(); # succeeds or dies based on scalar hints
+\&
+\& # Alternatively, hints can be set on subroutines we\*(Aqve
+\& # imported.
+\&
+\& use autodie::hints;
+\& use Some::Module qw(think_positive);
+\&
+\& BEGIN {
+\& autodie::hints\->set_hints_for(
+\& \e&think_positive,
+\& {
+\& fail => sub { $_[0] <= 0 }
+\& }
+\& )
+\& }
+\& use autodie qw(think_positive);
+\&
+\& think_positive(...); # Returns positive or dies.
+.Ve
+.SH DESCRIPTION
+.IX Header "DESCRIPTION"
+.SS Introduction
+.IX Subsection "Introduction"
+The autodie pragma is very smart when it comes to working with
+Perl's built-in functions. The behaviour for these functions are
+fixed, and \f(CW\*(C`autodie\*(C'\fR knows exactly how they try to signal failure.
+.PP
+But what about user-defined subroutines from modules? If you use
+\&\f(CW\*(C`autodie\*(C'\fR on a user-defined subroutine then it assumes the following
+behaviour to demonstrate failure:
+.IP \(bu 4
+A false value, in scalar context
+.IP \(bu 4
+An empty list, in list context
+.IP \(bu 4
+A list containing a single undef, in list context
+.PP
+All other return values (including the list of the single zero, and the
+list containing a single empty string) are considered successful. However,
+real-world code isn't always that easy. Perhaps the code you're working
+with returns a string containing the word "FAIL" upon failure, or a
+two element list containing \f(CW\*(C`(undef, "human error message")\*(C'\fR. To make
+autodie work with these sorts of subroutines, we have
+the \fIhinting interface\fR.
+.PP
+The hinting interface allows \fIhints\fR to be provided to \f(CW\*(C`autodie\*(C'\fR
+on how it should detect failure from user-defined subroutines. While
+these \fIcan\fR be provided by the end-user of \f(CW\*(C`autodie\*(C'\fR, they are ideally
+written into the module itself, or into a helper module or sub-class
+of \f(CW\*(C`autodie\*(C'\fR itself.
+.SS "What are hints?"
+.IX Subsection "What are hints?"
+A \fIhint\fR is a subroutine or value that is checked against the
+return value of an autodying subroutine. If the match returns true,
+\&\f(CW\*(C`autodie\*(C'\fR considers the subroutine to have failed.
+.PP
+If the hint provided is a subroutine, then \f(CW\*(C`autodie\*(C'\fR will pass
+the complete return value to that subroutine. If the hint is
+any other value, then \f(CW\*(C`autodie\*(C'\fR will smart-match against the
+value provided. In Perl 5.8.x there is no smart-match operator, and as such
+only subroutine hints are supported in these versions.
+.PP
+Hints can be provided for both scalar and list contexts. Note
+that an autodying subroutine will never see a void context, as
+\&\f(CW\*(C`autodie\*(C'\fR always needs to capture the return value for examination.
+Autodying subroutines called in void context act as if they're called
+in a scalar context, but their return value is discarded after it
+has been checked.
+.SS "Example hints"
+.IX Subsection "Example hints"
+Hints may consist of subroutine references, objects overloading
+smart-match, regular expressions, and depending on Perl version possibly
+other things. You can specify different hints for how
+failure should be identified in scalar and list contexts.
+.PP
+These examples apply for use in the \f(CW\*(C`AUTODIE_HINTS\*(C'\fR subroutine and when
+calling \f(CW\*(C`autodie::hints\->set_hints_for()\*(C'\fR.
+.PP
+The most common context-specific hints are:
+.PP
+.Vb 2
+\& # Scalar failures always return undef:
+\& { scalar => sub { !defined($_[0]) } }
+\&
+\& # Scalar failures return any false value [default expectation]:
+\& { scalar => sub { ! $_[0] } }
+\&
+\& # Scalar failures always return zero explicitly:
+\& { scalar => sub { defined($_[0]) && $_[0] eq \*(Aq0\*(Aq } }
+\&
+\& # List failures always return an empty list:
+\& { list => sub { !@_ } }
+\&
+\& # List failures return () or (undef) [default expectation]:
+\& { list => sub { ! @_ || @_ == 1 && !defined $_[0] } }
+\&
+\& # List failures return () or a single false value:
+\& { list => sub { ! @_ || @_ == 1 && !$_[0] } }
+\&
+\& # List failures return (undef, "some string")
+\& { list => sub { @_ == 2 && !defined $_[0] } }
+\&
+\& # Unsuccessful foo() returns \*(AqFAIL\*(Aq or \*(Aq_FAIL\*(Aq in scalar context,
+\& # returns (\-1) in list context...
+\& autodie::hints\->set_hints_for(
+\& \e&foo,
+\& {
+\& scalar => qr/^ _? FAIL $/xms,
+\& list => sub { @_ == 1 && $_[0] eq \-1 },
+\& }
+\& );
+\&
+\& # Unsuccessful foo() returns 0 in all contexts...
+\& autodie::hints\->set_hints_for(
+\& \e&foo,
+\& {
+\& scalar => sub { defined($_[0]) && $_[0] == 0 },
+\& list => sub { @_ == 1 && defined($_[0]) && $_[0] == 0 },
+\& }
+\& );
+.Ve
+.PP
+This "in all contexts" construction is very common, and can be
+abbreviated, using the 'fail' key. This sets both the \f(CW\*(C`scalar\*(C'\fR
+and \f(CW\*(C`list\*(C'\fR hints to the same value:
+.PP
+.Vb 7
+\& # Unsuccessful foo() returns 0 in all contexts...
+\& autodie::hints\->set_hints_for(
+\& \e&foo,
+\& {
+\& fail => sub { @_ == 1 and defined $_[0] and $_[0] == 0 }
+\& }
+\& );
+\&
+\& # Unsuccessful think_positive() returns negative number on failure...
+\& autodie::hints\->set_hints_for(
+\& \e&think_positive,
+\& {
+\& fail => sub { $_[0] < 0 }
+\& }
+\& );
+\&
+\& # Unsuccessful my_system() returns non\-zero on failure...
+\& autodie::hints\->set_hints_for(
+\& \e&my_system,
+\& {
+\& fail => sub { $_[0] != 0 }
+\& }
+\& );
+.Ve
+.SH "Manually setting hints from within your program"
+.IX Header "Manually setting hints from within your program"
+If you are using a module which returns something special on failure, then
+you can manually create hints for each of the desired subroutines. Once
+the hints are specified, they are available for all files and modules loaded
+thereafter, thus you can move this work into a module and it will still
+work.
+.PP
+.Vb 2
+\& use Some::Module qw(foo bar);
+\& use autodie::hints;
+\&
+\& autodie::hints\->set_hints_for(
+\& \e&foo,
+\& {
+\& scalar => SCALAR_HINT,
+\& list => LIST_HINT,
+\& }
+\& );
+\& autodie::hints\->set_hints_for(
+\& \e&bar,
+\& { fail => SOME_HINT, }
+\& );
+.Ve
+.PP
+It is possible to pass either a subroutine reference (recommended) or a fully
+qualified subroutine name as the first argument. This means you can set hints
+on modules that \fImight\fR get loaded:
+.PP
+.Vb 4
+\& use autodie::hints;
+\& autodie::hints\->set_hints_for(
+\& \*(AqSome::Module:bar\*(Aq, { fail => SCALAR_HINT, }
+\& );
+.Ve
+.PP
+This technique is most useful when you have a project that uses a
+lot of third-party modules. You can define all your possible hints
+in one-place. This can even be in a sub-class of autodie. For
+example:
+.PP
+.Vb 1
+\& package my::autodie;
+\&
+\& use parent qw(autodie);
+\& use autodie::hints;
+\&
+\& autodie::hints\->set_hints_for(...);
+\&
+\& 1;
+.Ve
+.PP
+You can now \f(CW\*(C`use my::autodie\*(C'\fR, which will work just like the standard
+\&\f(CW\*(C`autodie\*(C'\fR, but is now aware of any hints that you've set.
+.SH "Adding hints to your module"
+.IX Header "Adding hints to your module"
+\&\f(CW\*(C`autodie\*(C'\fR provides a passive interface to allow you to declare hints for
+your module. These hints will be found and used by \f(CW\*(C`autodie\*(C'\fR if it
+is loaded, but otherwise have no effect (or dependencies) without autodie.
+To set these, your module needs to declare that it \fIdoes\fR the
+\&\f(CW\*(C`autodie::hints::provider\*(C'\fR role. This can be done by writing your
+own \f(CW\*(C`DOES\*(C'\fR method, using a system such as \f(CW\*(C`Class::DOES\*(C'\fR to handle
+the heavy-lifting for you, or declaring a \f(CW%DOES\fR package variable
+with a \f(CW\*(C`autodie::hints::provider\*(C'\fR key and a corresponding true value.
+.PP
+Note that checking for a \f(CW%DOES\fR hash is an \f(CW\*(C`autodie\*(C'\fR\-only
+short-cut. Other modules do not use this mechanism for checking
+roles, although you can use the \f(CW\*(C`Class::DOES\*(C'\fR module from the
+CPAN to allow it.
+.PP
+In addition, you must define a \f(CW\*(C`AUTODIE_HINTS\*(C'\fR subroutine that returns
+a hash-reference containing the hints for your subroutines:
+.PP
+.Vb 1
+\& package Your::Module;
+\&
+\& # We can use the Class::DOES from the CPAN to declare adherence
+\& # to a role.
+\&
+\& use Class::DOES \*(Aqautodie::hints::provider\*(Aq => 1;
+\&
+\& # Alternatively, we can declare the role in %DOES. Note that
+\& # this is an autodie specific optimisation, although Class::DOES
+\& # can be used to promote this to a true role declaration.
+\&
+\& our %DOES = ( \*(Aqautodie::hints::provider\*(Aq => 1 );
+\&
+\& # Finally, we must define the hints themselves.
+\&
+\& sub AUTODIE_HINTS {
+\& return {
+\& foo => { scalar => HINTS, list => SOME_HINTS },
+\& bar => { scalar => HINTS, list => MORE_HINTS },
+\& baz => { fail => HINTS },
+\& }
+\& }
+.Ve
+.PP
+This allows your code to set hints without relying on \f(CW\*(C`autodie\*(C'\fR and
+\&\f(CW\*(C`autodie::hints\*(C'\fR being loaded, or even installed. In this way your
+code can do the right thing when \f(CW\*(C`autodie\*(C'\fR is installed, but does not
+need to depend upon it to function.
+.SH "Insisting on hints"
+.IX Header "Insisting on hints"
+When a user-defined subroutine is wrapped by \f(CW\*(C`autodie\*(C'\fR, it will
+use hints if they are available, and otherwise reverts to the
+\&\fIdefault behaviour\fR described in the introduction of this document.
+This can be problematic if we expect a hint to exist, but (for
+whatever reason) it has not been loaded.
+.PP
+We can ask autodie to \fIinsist\fR that a hint be used by prefixing
+an exclamation mark to the start of the subroutine name. A lone
+exclamation mark indicates that \fIall\fR subroutines after it must
+have hints declared.
+.PP
+.Vb 2
+\& # foo() and bar() must have their hints defined
+\& use autodie qw( !foo !bar baz );
+\&
+\& # Everything must have hints (recommended).
+\& use autodie qw( ! foo bar baz );
+\&
+\& # bar() and baz() must have their hints defined
+\& use autodie qw( foo ! bar baz );
+\&
+\& # Enable autodie for all of Perl\*(Aqs supported built\-ins,
+\& # as well as for foo(), bar() and baz(). Everything must
+\& # have hints.
+\& use autodie qw( ! :all foo bar baz );
+.Ve
+.PP
+If hints are not available for the specified subroutines, this will cause a
+compile-time error. Insisting on hints for Perl's built-in functions
+(eg, \f(CW\*(C`open\*(C'\fR and \f(CW\*(C`close\*(C'\fR) is always successful.
+.PP
+Insisting on hints is \fIstrongly\fR recommended.
+.SH Diagnostics
+.IX Header "Diagnostics"
+.IP "Attempts to set_hints_for unidentifiable subroutine" 4
+.IX Item "Attempts to set_hints_for unidentifiable subroutine"
+You've called \f(CW\*(C`autodie::hints\->set_hints_for()\*(C'\fR using a subroutine
+reference, but that reference could not be resolved back to a
+subroutine name. It may be an anonymous subroutine (which can't
+be made autodying), or may lack a name for other reasons.
+.Sp
+If you receive this error with a subroutine that has a real name,
+then you may have found a bug in autodie. See "BUGS" in autodie
+for how to report this.
+.ie n .IP "fail hints cannot be provided with either scalar or list hints for %s" 4
+.el .IP "fail hints cannot be provided with either scalar or list hints for \f(CW%s\fR" 4
+.IX Item "fail hints cannot be provided with either scalar or list hints for %s"
+When defining hints, you can either supply both \f(CW\*(C`list\*(C'\fR and
+\&\f(CW\*(C`scalar\*(C'\fR keywords, \fIor\fR you can provide a single \f(CW\*(C`fail\*(C'\fR keyword.
+You can't mix and match them.
+.ie n .IP "%s hint missing for %s" 4
+.el .IP "\f(CW%s\fR hint missing for \f(CW%s\fR" 4
+.IX Item "%s hint missing for %s"
+You've provided either a \f(CW\*(C`scalar\*(C'\fR hint without supplying
+a \f(CW\*(C`list\*(C'\fR hint, or vice-versa. You \fImust\fR supply both \f(CW\*(C`scalar\*(C'\fR
+and \f(CW\*(C`list\*(C'\fR hints, \fIor\fR a single \f(CW\*(C`fail\*(C'\fR hint.
+.SH ACKNOWLEDGEMENTS
+.IX Header "ACKNOWLEDGEMENTS"
+.IP \(bu 4
+Dr Damian Conway for suggesting the hinting interface and providing the
+example usage.
+.IP \(bu 4
+Jacinta Richardson for translating much of my ideas into this
+documentation.
+.SH AUTHOR
+.IX Header "AUTHOR"
+Copyright 2009, Paul Fenwick <pjf@perltraining.com.au>
+.SH LICENSE
+.IX Header "LICENSE"
+This module is free software. You may distribute it under the
+same terms as Perl itself.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+autodie, Class::DOES