Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用插件编写Perl对象?_Perl - Fatal编程技术网

如何使用插件编写Perl对象?

如何使用插件编写Perl对象?,perl,Perl,如何使用可扩展代码编写Perl对象?我在考虑驱动程序或一些配置,用户可以在其中传递字符串“Classname::Class”或其他内容。谢谢 例如,对于图形类: my $spg = Graph::ShortestPathGraph->new; $spg->Algorithm( "Graph::DFS" ); $spg->solve; $spg->Algorithm( "Graph::BFS" ); $spg->solve; 可能会帮助你实现你想要的。这里是一个简

如何使用可扩展代码编写Perl对象?我在考虑驱动程序或一些配置,用户可以在其中传递字符串“Classname::Class”或其他内容。谢谢

例如,对于图形类:

my $spg = Graph::ShortestPathGraph->new;
$spg->Algorithm( "Graph::DFS" );
$spg->solve;

$spg->Algorithm( "Graph::BFS" );
$spg->solve;

可能会帮助你实现你想要的。

这里是一个简单的自制示例。一旦您理解了它,您就可以继续学习旨在消除这种单调乏味的模块:

#!/usr/bin/perl

package Me::Mine;

use base 'Class::Accessor';

__PACKAGE__->mk_accessors( qw( dumper ) );

sub dump {
    my $self = shift;
    my $dumper = $self->dumper;
    eval "require $dumper";
    print "Dumping using $dumper\n", $dumper->Dump([ $self ]);
    return;
}

package main;

use strict; use warnings;

my $me = Me::Mine->new;
my $you = Me::Mine->new;

$me->dumper('Data::Dumper');
$you->dumper('YAML');

$_->dump for $me, $you;
输出:

Dumping using Data::Dumper $VAR1 = bless( { 'dumper' => 'Data::Dumper' }, 'Me::Mine' ); Dumping using YAML --- YAML --- - !!perl/hash:Me::Mine dumper: YAML 使用Data::Dumper进行转储 $VAR1=祝福({ “转储程序”=>“数据::转储程序” }“我的……”; 使用YAML进行倾倒 ---亚马尔 --- - !!perl/hash:Me::Mine 翻车机:YAML 如何编写可扩展代码

有计划。假设您正在编写一个用于绘制曲线的算法 一组点。你需要这些点的一个来源,一个用来绘图的地方 它们,以及一种插值不在 设定

(请注意,假设“图形”在这里的意思是“图表”,而不是 离散数学意义上的图形。)

让我们定义表示这些操作的角色。来源 积分必须能够为我们提供以下积分:

 package Graphomatic::PointSource;
 use Moose::Role;

 requires 'get_points'; # return a list of points

 1;
绘图仪必须允许我们绘制点:

 package Graphomatic::Plot;
 use Moose::Role;

 requires 'plot_point'; # plot a point
 requires 'show_graph'; # show the final graph

 1;
当给定两个相邻点时,插值器必须给我们一个点:

 package Graphomatic::Interpolate;
 use Moose::Role;

 requires 'interpolate_point';

 1;
现在,我们只需要根据这些来编写我们的主应用程序 角色:

现在只需定义一些源代码实现。 让我们从文件中读取点:

package Graphomatic::PointSource::File;

use Moose;
use MooseX::FileAttribute;

# ensure, at compile-time, that this class is a valid point
# source
with 'Graphomatic::PointSource';

has_file 'dataset' => ( must_exist => 1, required => 1 );

sub get_points {
    my $self = shift;

    return parse $self->dataset->slurp;
}

1;
并打印到Z窗口系统:

package Graphomatic::Plot::Z;
use Moose;
use Z;

with 'Graphomatic::Plot';

has 'window' => ( is => 'ro', isa => 'Z::Window', lazy_build => 1);

sub _build_window { return Z->new_window }

sub plot_point {
    my ($self, $point) = @_;

    $self->window->plot_me_a_point_kthx($point->x, $point->y);
}

sub show_plot {
    my $self = shift;
    $self->window->show;
}

1;
然后用随机数生成器进行插值(嘿,我很懒,而且 不查找双三次插值:P):

现在,我们可以将所有部件组装成一个工作程序:

use Graphomatic::PointSource::File;
use Graphomatic::Plot::Z;
use Graphomatic::Interpolate::Random;

my $graphomatic = Graphomatic->new(
   source => Graphomatic::PointSource::File->new(
       file => 'data.dat',
   ),
   plot        => Graphomatic::Plot::Z->new,
   interpolate => Graphomatic::Interpolate::Random->new,
);

$graphomatic->run;
现在,您可以干净地自定义任何零件,而不影响 其他部分,只需实现“完成”所需任务的新类 角色。(如果他们说‘有……’,但不符合要求, 一旦加载类,就会出现错误。如果尝试 将实例用作不“执行”正确角色的参数 他会死的

输入安全,这是一件美妙的事情。)

至于处理配置文件,只需以某种方式读取名称和参数, 然后:

my $interpolate_class = get_config('interpolate_class');
Class::MOP::load_class($interpolate_class);
my $interpolate = $interpolate_class->new( %interpolate_class_args );

my $graphomatic = Graphomatic->new( interpolate => $interpolate, ... );
这是一种很好的自动化方法。

签出,以及

如果该类不存在,则抛出一个错误。但是,如果您想自己创建Algo类,那么制作它们可能会更好


有大量使用Moose预先制作的解决方案可以解决此问题,请查看CPAN。

请提供一个更详细的示例,说明您试图解决的问题。一些伪代码会很好。不要执行
eval“require$dumper”
。这使我成为一个悲伤的弗里多。将模块名转换为其文件名并不难。甚至还有一个方便的CPAN项目:@friedo你能扩展一下吗?我的意思是,这是一次性代码,只是为了说明一种技术,因此没有错误/参数检查,但是
eval“require$dumper”
有什么特别的错误(如?推荐的那样,我有一个(可能是不合理的)厌恶所有形式的字符串
eval
,除非它是绝对必要的。在这种情况下,它不是必要的,因为很容易获得模块文件名,所以您可以使用
my$mod_file=module_path$dumper;require$mod_file;
use Graphomatic::PointSource::File;
use Graphomatic::Plot::Z;
use Graphomatic::Interpolate::Random;

my $graphomatic = Graphomatic->new(
   source => Graphomatic::PointSource::File->new(
       file => 'data.dat',
   ),
   plot        => Graphomatic::Plot::Z->new,
   interpolate => Graphomatic::Interpolate::Random->new,
);

$graphomatic->run;
my $interpolate_class = get_config('interpolate_class');
Class::MOP::load_class($interpolate_class);
my $interpolate = $interpolate_class->new( %interpolate_class_args );

my $graphomatic = Graphomatic->new( interpolate => $interpolate, ... );
package MyClass;
use Moose;
use MooseX::Types::LoadableClass qw/ClassName/;

has 'algo' => (
    is => 'ro'
    , isa => ClassName
    , coerce => 1
);

sub solve {
    my $self = shift;
    my $algo = $self->algo->new;
    # stuff using algo
}


## These work:
Graph::ShortestPathGraph->new({ algo => 'Graph::DFS' })->solve;
Graph::ShortestPathGraph->new({ algo => 'Graph::BFS' })->solve;

## As does this:
my $gspg = Graph::ShortestPathGraph->new;
$gspg->algo('Graph::BFS');
$gspg->solve;