title: Recursive subroutine
body: <p>Let's say I have a pool of packages a, b, c,... each package has name, version and dependencies. </p>
  
  <p>In below code, <strong>get-cand</strong> sub takes a package and returns the candidates from the pool (along with their dependencies recursively).</p>
  
  <p>so if it took package named <strong>c</strong>, and the pool has</p>
  
  <p>Package c1:
  name <strong>c</strong>, version <strong>1</strong>, dep <strong>a</strong> (any version) and <strong>b</strong> (version <strong>1</strong>)</p>
  
  <p>Package c2:
  name <strong>c</strong>, version <strong>2</strong>, dep <strong>b</strong> (version 2)</p>
  
  <p>it will return the following data structure:</p>
  
  <pre><code>((c1 ((((a1 ()) (a2 ()))) (((b1 ()))))) (c2 ((((b2 ()))))))  # can't figure out how to get rid of empty lists here
  </code></pre>
  
  <p>I'm trying to write <strong>select-cand</strong> sub that will take the above data structure and the goal is to return the first candidate that doesn't conflict (with installed packages), and recursively check it's dependencies as well. </p>
  
  <p>so the sub should work like this:</p>
  
  <ul>
  <li>Check <strong>c1</strong>, if conflicts returned False, take <strong>c1</strong> and descend to it's deps</li>
  <li>(now in c1 deps) Check <strong>a1</strong>, if conflicts returned True, check next candidate (<strong>a2</strong>)</li>
  </ul>
  
  <p>eventually it should return [c1 a2 b1] or [c2 b2] for successful run or nothing if all candidates conflicts.</p>
  
  <p>but at the moment <strong>select-cand</strong> sub returns: [c1 a1 a2 c2 b2] which is wrong, because I only need either c1 (and it's deps recursively) or c2.</p>
  
  <p>(<strong>conflicts</strong> is a place holder sub, at the moment it just  exclude b1 package for testing purpose) </p>
  
  <pre><code>#!/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 =&gt; 'a', version =&gt; Version.new: &lt;1&gt;;
  my $a2 = Pkg.new: name =&gt; 'a', version =&gt; Version.new: &lt;2&gt;;
  my $b1 = Pkg.new: name =&gt; 'b', version =&gt; Version.new: &lt;1&gt;;
  my $b2 = Pkg.new: name =&gt; 'b', version =&gt; Version.new: &lt;2&gt;;
  my $c1 = Pkg.new: name =&gt; 'c', version =&gt; Version.new: &lt;1&gt;;
  my $c2 = Pkg.new: name =&gt; 'c', version =&gt; Version.new: &lt;2&gt;;
  
  $c1.dep.push: Pkg.new(name =&gt; 'a');
  $c1.dep.push: Pkg.new(name =&gt; 'b', version =&gt; Version.new: &lt;1&gt;);
  
  $c2.dep.push: Pkg.new(name =&gt; 'b', version =&gt; Version.new: &lt;2&gt;);
  
  %pkgs&lt;a&gt; .push: $a1, $a2;
  %pkgs&lt;b&gt; .push: $b1, $b2;
  %pkgs&lt;c&gt; .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( -&gt; $pkg {
              ($pkg, $pkg.dep.map( -&gt; $pkg {
                  get-cand($pkg).Slip
              }).Slip)
          }).cache;
      }
  }
  
  sub conflicts (Pkg $pkg) {
    return True if $pkg.name eq &lt;a&gt; and $pkg.version eq &lt;1&gt;; 
    #take $pkg.Str if $pkg.name eq &lt;a&gt; and $pkg.version eq &lt;1&gt;; 
  }
  
  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 =&gt; 'c';
  
  my @cand =  get-cand $c;
  my @selected = select-cand @cand;
  
  say @selected; # [(c1 () (a2) (b1))]
  </code></pre>