对象数组

时间:2019-05-22 21:48:48

标签: perl6 raku

比方说,我想连接到两个软件包存储库,查询软件包名称,合并存储库的结果并对其进行处理(过滤,唯一,优先级排序...),这是一个很好的方法那?

我想做的是创建两个Array对象(每个回购中都有Cro::HTTP::Client个对象)base-uri,当我需要发出HTTP请求时,我调用@a>>.get ,然后一起处理来自仓库的结果。

我已附上我要执行的操作的摘要。但我想看看是否有更好的方法可以做到这一点。或者如果以下链接中提到的方法适合该用例! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/

use Cro::HTTP::Client;

class Repo {

  has $.name;
  has Cro::HTTP::Client $!client;
  has Cro::Uri $.uri;
  has Bool $.disable = False;

  submethod TWEAK () {
    $!client = Cro::HTTP::Client.new(base-uri => $!uri, :json);
  }

  method get (:$package) {

    my $path = <x86_64?>;
    my $resp = await $!client.get($path ~ $package);
    my $json = await $resp.body;
    return $json;
  }
}


class AllRepos {

  has Repo @.repo;

  method get (:$package) {

    # check if some repos are disabled
    my @candidate = @!repo>>.get(:$package).unique(:with(&[eqv])).flat;

    # do furthre processign of the data then return it;
    return @candidate;

  }
}

my $repo1 = Repo.new: name => 'repo1', uri => Cro::Uri.new(:uri<http://localhost:80>);
my $repo2 = Repo.new: name => 'repo2', uri => Cro::Uri.new(:uri<http://localhost:77>);

my @repo = $repo1, $repo2;

my $repos = AllRepos.new: :@repo;


#my @packages = $repos.get: package => 'rakudo';

1 个答案:

答案 0 :(得分:6)

  

比方说,我想连接到两个软件包存储库,查询软件包名称,合并存储库的结果并对其进行处理(过滤,唯一,优先级排序...),这是一个很好的方法那?

您显示的代码在原理上似乎是一种不错的方法 ,但实际上目前还不是。

hyperoperators such as >>

  • 分配一个操作(在您的情况下,连接并进行查询)...

  • ...到一个或两个输入复合数据结构的叶子(在您的情况下为一个数组@!repo的元素)...

  • ...具有逻辑上的并行语义(通过使用超级操作符,您声明您有责任认为该操作的并行调用不会相互干扰,这对于连接和查询来说听起来很合理)...

  • ...,如果超级操作符是一元运算符,则返回与原始结构形状相同的结果复合数据结构(在您的情况下适用,因为您应用了>>,一元运算符,其左侧带有一个参数,因此>>.get的结果只是一个新数组,就像输入@!repo一样),或者其形状是形状的超组合如果超级操作符是二进制操作符,例如>>op<< ...

  • ...然后可以进一步处理(在您的情况下,使用.unique,将产生结果Seq)...

  • ...,然后将其元素分配回另一个数组(@candidate)。

因此,您的选择在原则上是不错的选择,但对并行性的承诺仅是语义上的,现在Rakudo编译器从不利用它,因此它实际上将按顺序运行您的代码,这可能不是一个合适的选择在实践中。

相反,我建议您考虑:

  • 使用map将操作分布在多个元素上(以一种浅层的方式; map不会像超级操作符,deepmap等那样递归地归入较深的结构。 ,但是对于您的用例来说就可以了)...

  • ...与race method结合使用,它并行化了进行的方法。

所以您可以写:

my @candidate =
  @!repo.hyper.map(*.get: :$package).unique(:with(&[eqv])).flat;

或者,在Using Perl 6中检出任务94。

  

如果以下链接中提到的方法适用于此用例! https://perl6advent.wordpress.com/2013/12/08/day-08-array-based-objects/

我不这么认为。那是关于构造一个通用容器,该容器就像一个数组,但与内置Array有一些差异,值得烘焙成新类型。

我几乎可以想象与您的用例有关的事情-例如,如果数组类型是在Any或{{1}上定义的,则自动超分配对其调用的方法调用的数组类型}(而不是MuArray),即按照我的上述描述,但是使用代码List而不是@!repo.get...。但这是否值得(假设它可以工作,我除了想出这个答案的想法外就没有想到过)吗?我对此表示怀疑。

更一般地...

您所寻找的似乎是食谱一样的材料。也许是在the reddit sub /r/perl6上发布的问题了?