# autobox
"12.34"->is_number;
1->upto(5);
"10, 20, 30, 40"->split(qr{, ?})->elements;
(1,2,3,4,5,"a","b")->grep(sub{ $_->is_number })->sum->say;
my %hash = (foo=>123, bar => 321);
%hash->each(sub{
my ($k, $v) = @_;
});
喜欢链式调用风格的人可能会非常喜欢这种写法。那么问题来了。这是怎么做的,如果某个类型没现成的方法想自己实现要怎么办呢?
autobox::Core 的实现很简单。比如其字符串相关部分就是这样:
package autobox::Core;
use base 'autobox';
sub import {
shift->SUPER::import(DEFAULT => 'autobox::Core::', @_);
}
package autobox::Core::SCALAR;
sub chomp { CORE::chomp($_[0]); }
完整情况下, autobox 一共可以扩展下面这些数据类型:
* UNDEF
* INTEGER
* FLOAT
* NUMBER
* STRING
* SCALAR
* ARRAY
* HASH
* CODE
* UNIVERSAL
而定义 DEFAULT 的作用就是表示各数据类型自动查找 DEFAULT 定义的这个名字空间下的同名类。相当于字符串类型就是:
shift->SUPER::import(SCALAR => 'autobox::Core::SCALAR');
键值对还支持传递数组引用。这样就能对单个数据类型绑定多个类的函数。而这也是实现我们前面期望扩展个别方法的地方。比如实现一个类似 Perl6 中字符串的 `->words()` 方法:
{
package autobox::Core::SCALAR::Extends;
sub words {
CORE::split(/\s+/, $_[0]);
}
}
use autobox::Core SCALAR => ['autobox::Core::SCALAR', 'autobox::Core::SCALAR::Extends'];
my @array = "hello world"->words;
@array->each(sub {
$_[0]->say;
});
传一个数组给 autobox::Core,这样既保持了 autobox::Core 原有的方法,又添加了自己想要的效果。脚本运行效果如下:
hello
world
btw: 代码中用了 `CORE::`,目前 Perl5 是尽量把内置函数都转移到这个 CORE 名下了。