假设我有一个包 a、b、c、... 每个包都有名称、版本和依赖项。
在下面的代码中,get-cand sub 接受一个包并从池中返回候选者(以及它们的递归依赖项)。
因此,如果它采用名为c的包,并且池中有
包 c1:名称c,版本1,dep a(任何版本)和b(版本1)
包 c2:名称c,版本2,dep b(版本 2)
它将返回以下数据结构:
((c1 ((((a1 ()) (a2 ()))) (((b1 ()))))) (c2 ((((b2 ())))))) # can't figure out how to get rid of empty lists here
我正在尝试编写将采用上述数据结构的select-cand sub,目标是返回第一个不冲突的候选者(与已安装的包),并递归检查它的依赖关系。
所以子应该像这样工作:
- 检查c1,如果冲突返回 False,则取c1并下降到它的 deps
- (现在在 c1 部门)检查a1,如果冲突返回 True,检查下一个候选者(a2)
最终它应该返回 [c1 a2 b1] 或 [c2 b2] 以成功运行,如果所有候选者都冲突,则返回任何内容。
但目前select-cand sub 返回: [c1 a1 a2 c2 b2] 这是错误的,因为我只需要 c1(它是递归的)或 c2。
(冲突是一个占位符子,目前它只是排除 b1 包用于测试目的)
#!/usr/bin/env perl6
my %pkgs;
class Pkg {
has $.name;
has Version $.version = Version.new;
has Pkg @.dep;
method Str {
$!name ~ $!version;
}
}
my $a1 = Pkg.new: name => 'a', version => Version.new: <1>;
my $a2 = Pkg.new: name => 'a', version => Version.new: <2>;
my $b1 = Pkg.new: name => 'b', version => Version.new: <1>;
my $b2 = Pkg.new: name => 'b', version => Version.new: <2>;
my $c1 = Pkg.new: name => 'c', version => Version.new: <1>;
my $c2 = Pkg.new: name => 'c', version => Version.new: <2>;
$c1.dep.push: Pkg.new(name => 'a');
$c1.dep.push: Pkg.new(name => 'b', version => Version.new: <1>);
$c2.dep.push: Pkg.new(name => 'b', version => Version.new: <2>);
%pkgs<a> .push: $a1, $a2;
%pkgs<b> .push: $b1, $b2;
%pkgs<c> .push: $c1, $c2;
sub return-pkg (Pkg $pkg) {
my @pkgs = flat %pkgs{$pkg.name};
return grep {$_.version ~~ $pkg.version}, @pkgs;
}
sub get-cand (Pkg $pkg) {
gather {
take return-pkg($pkg).map( -> $pkg {
($pkg, $pkg.dep.map( -> $pkg {
get-cand($pkg).Slip
}).Slip)
}).cache;
}
}
sub conflicts (Pkg $pkg) {
return True if $pkg.name eq <a> and $pkg.version eq <1>;
#take $pkg.Str if $pkg.name eq <a> and $pkg.version eq <1>;
}
multi select-cand (Pkg $pkg) {
return $pkg.Str if not conflicts $pkg;
}
multi select-cand (@cand) {
gather {
@cand.map({ .first({ take select-cand $_ })});
}
}
my $c = Pkg.new: name => 'c';
my @cand = get-cand $c;
my @selected = select-cand @cand;
say @selected; # [(c1 () (a2) (b1))]