The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

=pod
=head1 NAME
autobox - call methods on native types
=head1 SYNOPSIS
use autobox;
# integers
my $range = 10->to(1); # [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
# floats
my $error = 3.1415927->minus(22/7)->abs();
# strings
my @list = 'SELECT * FROM foo'->list();
my $greeting = "Hello, world!"->upper(); # "HELLO, WORLD!"
$greeting->for_each(\&character_handler);
# arrays and array refs
my $schwartzian = @_->map(...)->sort(...)->map(...);
my $hash = [ 'SELECT * FROM foo WHERE id IN (?, ?)', 1, 2 ]->hash();
# hashes and hash refs
{ alpha => 'beta', gamma => 'vlissides' }->for_each(...);
%hash->keys();
# code refs
my $plus_five = (\&add)->curry()->(5);
my $minus_three = sub { $_[0] - $_[1] }->reverse->curry->(3);
# can, isa, VERSION, import and unimport can be accessed via autobox_class
42->autobox_class->isa('MyNumber');
say []->autobox_class->VERSION;
=head1 DESCRIPTION
The autobox pragma allows methods to be called on integers, floats, strings, arrays,
hashes, and code references in exactly the same manner as blessed references.
Autoboxing is transparent: values are not blessed into their (user-defined)
implementation class (unless the method elects to bestow such a blessing) - they simply
use its methods as though they are.
The classes (packages) into which the native types are boxed are fully configurable.
By default, a method invoked on a non-object value is assumed to be
defined in a class whose name corresponds to the C<ref()> type of that
value - or SCALAR if the value is a non-reference.
This mapping can be overridden by passing key/value pairs to the C<use autobox>
statement, in which the keys represent native types, and the values
their associated classes.
As with regular objects, autoboxed values are passed as the first argument of the specified method.
Consequently, given a vanilla C<use autobox>:
"Hello, world!"->upper()
is invoked as:
SCALAR::upper("hello, world!")
while:
[ 1 .. 10 ]->for_each(sub { ... })
resolves to:
ARRAY::for_each([ 1 .. 10 ], sub { ... })
Values beginning with the array C<@> and hash C<%> sigils are passed by
reference, i.e. under the default bindings:
@array->join(', ')
@{ ... }->length()
%hash->keys()
%$hash->values()
are equivalent to:
ARRAY::join(\@array, ', ')
ARRAY::length(\@{ ... })
HASH::keys(\%hash)
HASH::values(\%$hash)
Multiple C<use autobox> statements can appear in the same scope. These are merged both "horizontally" (i.e.
multiple classes can be associated with a particular type) and "vertically" (i.e. multiple classes can be associated
with multiple types).
Thus:
use autobox SCALAR => 'Foo';
use autobox SCALAR => 'Bar';
- associates SCALAR types with a synthetic class whose C<@ISA> includes both Foo and Bar (in that order).
Likewise:
use autobox SCALAR => 'Foo';
use autobox SCALAR => 'Bar';
use autobox ARRAY => 'Baz';
and
use autobox SCALAR => [ 'Foo', 'Bar' ];
use autobox ARRAY => 'Baz';
- bind SCALAR types to the Foo and Bar classes and ARRAY types to Baz.
autobox is lexically scoped, and bindings for an outer scope
can be extended or countermanded in a nested scope:
{
use autobox; # default bindings: autobox all native types
...
{
# appends 'MyScalar' to the @ISA associated with SCALAR types
use autobox SCALAR => 'MyScalar';
...
}
# back to the default (no MyScalar)
...
}
Autoboxing can be turned off entirely by using the C<no> syntax:
{
use autobox;
...
no autobox;
...
}
- or can be selectively disabled by passing arguments to the C<no autobox> statement:
use autobox; # default bindings
no autobox qw(SCALAR);
[]->foo(); # OK: ARRAY::foo([])
"Hello, world!"->bar(); # runtime error
Autoboxing is not performed for barewords, i.e.
my $foo = Foo->new();
and:
my $foo = new Foo;
behave as expected.
Methods are called on native types by means of the L<arrow operator|perlop/"The Arrow Operator">. As with
regular objects, the right hand side of the operator can either be a bare method name or a variable containing
a method name or subroutine reference. Thus the following are all valid:
sub method1 { ... }
my $method2 = 'some_method';
my $method3 = sub { ... };
my $method4 = \&some_method;
" ... "->method1();
[ ... ]->$method2();
{ ... }->$method3();
sub { ... }->$method4();
A native type is only associated with a class if the type => class mapping
is supplied in the C<use autobox> statement. Thus the following will not work:
use autobox SCALAR => 'MyScalar';
@array->some_array_method();
- as no class is specified for the ARRAY type. Note: the result of calling a method
on a native type that is not associated with a class is the usual runtime error message:
Can't call method "some_array_method" on unblessed reference at ...
As a convenience, there is one exception to this rule. If C<use autobox> is invoked with no arguments
(ignoring the DEBUG option) the four main native types are associated with classes of the same name.
Thus:
use autobox;
- is equivalent to:
use autobox {
SCALAR => 'SCALAR',
ARRAY => 'ARRAY',
HASH => 'HASH',
CODE => 'CODE',
}
This facilitates one-liners and prototypes:
use autobox;
sub SCALAR::split { [ split '', $_[0] ] }
sub ARRAY::length { scalar @{$_[0]} }
print "Hello, world!"->split->length();
However, using these default bindings is not recommended as there's no guarantee that another
piece of code won't trample over the same namespace/methods.
=head1 OPTIONS
A mapping from native types to their user-defined classes can be specified
by passing a hashref or a list of key/value pairs to the C<use autobox> statement.
The following example shows the range of valid arguments:
use autobox {
SCALAR => 'MyScalar' # class name
ARRAY => 'MyNamespace::', # class prefix (ending in '::')
HASH => [ 'MyHash', 'MyNamespace::' ], # one or more class names and/or prefixes
CODE => ..., # any of the 3 value types above
INTEGER => ..., # any of the 3 value types above
FLOAT => ..., # any of the 3 value types above
NUMBER => ..., # any of the 3 value types above
STRING => ..., # any of the 3 value types above
UNDEF => ..., # any of the 3 value types above
UNIVERSAL => ..., # any of the 3 value types above
DEFAULT => ..., # any of the 3 value types above
DEBUG => ... # boolean or coderef
}
The INTEGER, FLOAT, NUMBER, STRING, SCALAR, ARRAY, HASH, CODE, UNDEF, DEFAULT and UNIVERSAL options can take
three different types of value:
=over
=item *
A class name, e.g.
use autobox INTEGER => 'MyInt';
This binds the specified native type to the specified class. All methods invoked on
values of type C<key> will be dispatched as methods of the class specified in
the corresponding C<value>.
=item *
A namespace: this is a class prefix (up to and including the final '::')
to which the specified type name (INTEGER, FLOAT, STRING etc.) will be appended:
Thus:
use autobox ARRAY => 'Prelude::';
is equivalent to:
use autobox ARRAY => 'Prelude::ARRAY';
=item *
A reference to an array of class names and/or namespaces. This associates multiple classes with the
specified type.
=back
=head2 DEFAULT
The C<DEFAULT> option specifies bindings for any of the four default types (SCALAR, ARRAY, HASH and CODE)
not supplied in the C<use autobox> statement. As with the other options, the C<value> corresponding to
the C<DEFAULT> C<key> can be a class name, a namespace, or a reference to an array containing one or
more class names and/or namespaces.
Thus:
use autobox {
STRING => 'MyString',
DEFAULT => 'MyDefault',
}
is equivalent to:
use autobox {
STRING => 'MyString',
SCALAR => 'MyDefault',
ARRAY => 'MyDefault',
HASH => 'MyDefault',
CODE => 'MyDefault',
}
Which in turn is equivalent to:
use autobox {
INTEGER => 'MyDefault',
FLOAT => 'MyDefault',
STRING => [ 'MyString', 'MyDefault' ],
ARRAY => 'MyDefault',
HASH => 'MyDefault',
CODE => 'MyDefault',
}
Namespaces in DEFAULT values have the default type name appended, which, in the case of defaulted SCALAR types,
is SCALAR rather than INTEGER, FLOAT etc.
Thus:
use autobox {
ARRAY => 'MyArray',
HASH => 'MyHash',
CODE => 'MyCode',
DEFAULT => 'MyNamespace::',
}
is equivalent to:
use autobox {
INTEGER => 'MyNamespace::SCALAR',
FLOAT => 'MyNamespace::SCALAR',
STRING => 'MyNamespace::SCALAR',
ARRAY => 'MyArray',
HASH => 'MyHash',
CODE => 'MyCode',
}
Any of the four default types can be exempted from defaulting to the DEFAULT value by supplying a value of undef:
use autobox {
HASH => undef,
DEFAULT => 'MyDefault',
}
42->foo # ok: MyDefault::foo
[]->bar # ok: MyDefault::bar
%INC->baz # not ok: runtime error
=head2 UNDEF
The pseudotype, UNDEF, can be used to autobox undefined values. These are not autoboxed by default.
This doesn't work:
use autobox;
undef->foo(); # runtime error
This works:
use autobox UNDEF => 'MyUndef';
undef->foo(); # ok
So does this:
use autobox UNDEF => 'MyNamespace::';
undef->foo(); # ok
=head2 NUMBER, SCALAR and UNIVERSAL
The virtual types NUMBER, SCALAR and UNIVERSAL function as macros or shortcuts which create
bindings for their subtypes. The type hierarchy is as follows:
UNIVERSAL -+
|
+- SCALAR -+
| |
| +- NUMBER -+
| | |
| | +- INTEGER
| | |
| | +- FLOAT
| |
| +- STRING
|
+- ARRAY
|
+- HASH
|
+- CODE
Thus:
use autobox NUMBER => 'MyNumber';
is equivalent to:
use autobox {
INTEGER => 'MyNumber',
FLOAT => 'MyNumber',
}
And:
use autobox SCALAR => 'MyScalar';
is equivalent to:
use autobox {
INTEGER => 'MyScalar',
FLOAT => 'MyScalar',
STRING => 'MyScalar',
}
Virtual types can also be passed to C<unimport> via the C<no autobox> syntax. This disables autoboxing
for the corresponding subtypes, e.g.
no autobox qw(NUMBER);
is equivalent to:
no autobox qw(INTEGER FLOAT);
Virtual type bindings can be mixed with ordinary bindings to provide fine-grained control over
inheritance and delegation. For instance:
use autobox {
INTEGER => 'MyInteger',
NUMBER => 'MyNumber',
SCALAR => 'MyScalar',
}
would result in the following bindings:
42->foo -> [ MyInteger, MyNumber, MyScalar ]
3.1415927->bar -> [ MyNumber, MyScalar ]
"Hello, world!"->baz -> [ MyScalar ]
Note that DEFAULT bindings take precedence over virtual type bindings, i.e.
use autobox {
UNIVERSAL => 'MyUniversal',
DEFAULT => 'MyDefault', # default SCALAR, ARRAY, HASH and CODE before UNIVERSAL
}
is equivalent to:
use autobox {
INTEGER => [ 'MyDefault', 'MyUniversal' ],
FLOAT => [ 'MyDefault', 'MyUniversal' ], # ... etc.
}
=head2 DEBUG
C<DEBUG> allows the autobox bindings for the current scope to be inspected,
either by dumping them to the console or passing them to a callback function.
This allows the computed bindings to be seen in "longhand".
The option is ignored if the value corresponding to the C<DEBUG> key is false.
If the value is a CODE ref, it is called with a reference to the hash
containing the computed bindings for the current scope.
Finally, if C<DEBUG> is true but not a CODE ref, the bindings are dumped
to STDERR.
Thus:
use autobox DEBUG => 1, ...
or
use autobox DEBUG => sub { ... }, ...
or
sub my_callback ($) {
my $hashref = shift;
...
}
use autobox DEBUG => \&my_callback, ...
=head1 METHODS
=head2 import
This method sets up autobox bindings for the current lexical scope. It can be used to implement
autobox extensions, i.e. lexically-scoped modules that provide autobox bindings for one or more
native types without requiring calling code to C<use autobox>.
This is done by subclassing autobox and overriding C<import>. This allows extensions to effectively
translate C<use MyModule> into a bespoke C<use autobox> call, e.g.:
package String::Trim;
use base qw(autobox);
sub import {
my $class = shift;
$class->SUPER::import(
STRING => 'String::Trim::String'
);
}
package String::Trim::String;
sub trim {
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
$string;
}
1;
Note that C<trim> is defined in an auxiliary class rather than in String::Trim itself to prevent
String::Trim's own methods (i.e. the methods it inherits from autobox) being exposed to C<STRING> types.
This module can now be used without a C<use autobox> statement to enable the C<trim> method in the current
lexical scope, e.g.:
#!/usr/bin/env perl
use String::Trim;
print " Hello, world! "->trim();
=head1 UNIVERSAL METHODS FOR AUTOBOXED TYPES
=head2 autobox_class
autobox adds a single method to all autoboxed types: C<autobox_class>. This can be used to
call L<UNIVERSAL|UNIVERSAL> methods, i.e. C<can>, C<DOES>, C<import>, C<isa>, C<unimport> and C<VERSION>, e.g.
if (sub { ... }->autobox_class->can('curry')) ...
if (42->autobox_class->isa('SCALAR')) ...
Note: C<autobox_class> must B<always> be used when calling these methods. Calling them
directly on native types produces the same results as calling them with autobox disabled
e.g.:
42->isa('NUMBER') # "" (interpreted as "42"->isa("NUMBER"))
[]->can('push') # Error: Can't call method "can" on unblessed reference
=head1 EXPORTS
=head2 type
autobox includes an additional module, autobox::universal, which exports a single subroutine, C<type>.
This sub returns the type of its argument within autobox (which is essentially longhand for the type names
used within perl). This value is used by autobox to associate a method invocant with its designated classes, e.g.
use autobox::universal qw(type);
type("42") # STRING
type(42) # INTEGER
type(42.0) # FLOAT
type(undef) # UNDEF
autobox::universal is loaded automatically by autobox, and, as its name suggests, can be used to install
a universal C<type> method for autoboxed values, e.g.
use autobox UNIVERSAL => 'autobox::universal';
42->type # INTEGER
3.1415927->type # FLOAT
%ENV->type # HASH
=head1 CAVEATS
=head2 Performance
Calling
"Hello, world!"->length()
is slightly slower than the equivalent method call on a string-like object, and significantly slower than
length("Hello, world!")
=head2 Gotchas
=head3 Precedence
Due to Perl's precedence rules, some autoboxed literals may need to be parenthesized:
For instance, while this works:
my $curried = sub { ... }->curry();
this doesn't:
my $curried = \&foo->curry();
The solution is to wrap the reference in parentheses:
my $curried = (\&foo)->curry();
The same applies for signed integer and float literals:
# this works
my $range = 10->to(1);
# this doesn't work
my $range = -10->to(10);
# this works
my $range = (-10)->to(10);
=head3 print BLOCK
Perl's special-casing for the C<print BLOCK ...> syntax (see L<perlsub>) means that C<print { expression() } ...>
(where the curly brackets denote an anonymous HASH ref) may require some further disambiguation:
# this works
print { foo => 'bar' }->foo();
# and this
print { 'foo', 'bar' }->foo();
# and even this
print { 'foo', 'bar', @_ }->foo();
# but this doesn't
print { @_ }->foo() ? 1 : 0;
In the latter case, the solution is to supply something
other than a HASH ref literal as the first argument
to C<print()>:
# e.g.
print STDOUT { @_ }->foo() ? 1 : 0;
# or
my $hashref = { @_ };
print $hashref->foo() ? 1 : 0;
# or
print '', { @_ }->foo() ? 1 : 0;
# or
print '' . { @_ }->foo() ? 1 : 0;
# or even
{ @_ }->print_if_foo(1, 0);
=head3 eval EXPR
Like most pragmas, autobox performs operations at compile time, and,
as a result, runtime string C<eval>s are not executed within its scope, i.e.
this doesn't work:
use autobox;
eval "42->foo";
The workaround is to use autobox within the C<eval>, e.g.
eval <<'EOS';
use autobox;
42->foo();
EOS
Note that the C<eval BLOCK> form works as expected:
use autobox;
eval { 42->foo() }; # OK
=head3 Operator Overloading
Operator overloading via the L<overload> pragma doesn't (automatically) work.
autobox works by lexically overriding the L<arrow operator|perlop/"The Arrow Operator">.
It doesn't bless native types into objects, so overloading - or any other kind of "magic"
which depends on values being blessed - doesn't apply.
=head1 VERSION
3.0.2
=head1 SEE ALSO
=over
=item * L<autobox::Core|autobox::Core>
=item * L<Moose::Autobox>
=item * L<perl5i|perl5i>
=item * L<Scalar::Properties|Scalar::Properties>
=back
=head1 AUTHOR
chocolateboy <chocolate@cpan.org>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2003-2024 by chocolateboy.
This library is free software; you can redistribute it and/or modify it under the
=cut