Source

p5-perlx-maybe / lib / PerlX / Maybe.pm

package PerlX::Maybe;

use 5.008;
use strict;

our (@EXPORT, @ISA);
BEGIN {
	$PerlX::Maybe::AUTHORITY = 'cpan:TOBYINK';
	$PerlX::Maybe::VERSION   = '0.001';
	
	require Exporter;
	@ISA       = qw/Exporter/;
	@EXPORT    = qw/maybe/;
}

sub maybe ($$@)
{
	my ($x, $y, @rest) = @_;
	my @r = (
		(defined $y && defined $x ? ($x, $y) : ()),
		@rest,
		);
	return @r;
}

__FILE__
__END__

=head1 NAME

PerlX::Maybe - return a pair only if they are both defined

=head1 SYNOPSIS

You once wrote:

 my $bob = Person->new(
    defined $name ? (name => $name) : (),
    defined $age ? (age => $age) : (),
    );

Now you can write:

 my $bob = Person->new(
    maybe name => $name,
    maybe age  => $age,
    );

=head1 DESCRIPTION

Moose classes (and some other classes) distinguish between an attribute
being unset and the attribute being set to undef. Supplying a constructor
arguments like this:

 my $bob = Person->new(
    name => $name,
    age => $age,
    );

Will result in the C<name> and C<age> attributes possibly being set to
undef (if the corresponding C<$name> and C<$age> variables are not defined),
which may violate the Person class' type constraints.

(Note: if you are the I<author> of the class in question, you can solve
this using L<MooseX::UndefTolerant>. However, some of us are stuck using
non-UndefTolerant classes written by third parties.)

To ensure that the Person constructor does not try to set a name or age
at all when they are undefined, ugly looking code like this is often used:

 my $bob = Person->new(
    defined $name ? (name => $name) : (),
    defined $age ? (age => $age) : (),
    );

A slightly more elegant solution is the C<maybe> function:

=head2 C<< maybe $x => $y, @rest >>

This function checks that C<< $x >> and C<< $y >> are both defined. If they
are, it returns them both as a list; otherwise it returns the empty list.

If C<< @rest >> is provided, it is unconditionally appended to the end of
whatever list is returned.

The combination of these behaviours allows the following very sugary syntax
to "just work".

 my $bob = Person->new(
         name      => $name,
         address   => $addr,
   maybe phone     => $tel,
   maybe email     => $email,
         unique_id => $id,
   );

This function is exported by default.

=head1 BUGS

Please report any bugs to
L<http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe>.

=head1 SEE ALSO

L<Syntax::Feature::Maybe>.

L<MooseX::UndefTolerant>, L<PerlX::Perform>, L<Exporter>.

=head1 AUTHOR

Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

=head1 COPYRIGHT AND LICENCE

This software is copyright (c) 2012 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.

=head1 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.