在 Raku 中,如何编写相当于 Haskell 的 span 函数?

use*_*725 18 haskell predicate list raku


\n

在 Raku 中,如何编写与 Haskell 函数等价的span函数?

\n

在 Haskell 中,给定一个谓词和一个列表,可以将列表分为两部分:

\n
    \n
  • 满足谓词的元素的最长前缀
  • \n
  • 列表的其余部分
  • \n
\n

例如,Haskell 表达式 \xe2\x80\xa6

\n
span (< 10) [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4]\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6 计算为 \xe2\x80\xa6

\n
([2,2,2,5,5,7],[13,9,6,2,20,4])\n
Run Code Online (Sandbox Code Playgroud)\n

如何编写与 Haskell 函数相当的 Raku 函数span

\n
\n

更新1

\n

根据@chenyf的回答,我开发了以下span子例程(后来的额外更新反映了保持忠实于Haskell函数正逻辑所需的否定谓词)\xe2\x80\xa6spanspan

\n
sub span( &predicate, @numberList )\n  {\n  my &negatedPredicate = { ! &predicate($^x) } ;\n  my $idx = @numberList.first(&negatedPredicate):k ;\n  my @lst is Array[List] = @numberList[0..$idx-1], @numberList[$idx..*] ;\n  @lst ;\n  } # end sub span\n\nsub MAIN()\n  {\n  my &myPredicate = { $_ <= 10 } ;\n  my @myNumberList is Array[Int] = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4] ;\n  my @result is Array[List] = span( &myPredicate, @myNumberList ) ;\n\n  say \'@result is ...\' ;\n  say @result ;\n  say \'@result[0] is ...\' ;\n  say @result[0] ;\n  say @result[0].WHAT ;\n  say \'@result[1] is ...\' ;\n  say @result[1] ;\n  say @result[1].WHAT ;\n  } # end sub MAIN\n
Run Code Online (Sandbox Code Playgroud)\n

程序输出为\xe2\x80\xa6

\n
@result is ...\n[(2 2 2 5 5 7) (13 9 6 2 20 4)]\n@result[0] is ...\n(2 2 2 5 5 7)\n(List)\n@result[1] is ...\n(13 9 6 2 20 4)\n(List)\n
Run Code Online (Sandbox Code Playgroud)\n
\n

更新2

\n

利用发布到StackOverflow的有关 Raku 的信息Nil,以下子例程的更新草案span为 \xe2\x80\xa6

\n
sub span( &predicate, @numberList )\n  {\n  my &negatedPredicate = { ! &predicate($^x) } ;\n  my $idx = @numberList.first( &negatedPredicate ):k ;\n  if Nil ~~ any($idx) { $idx = @numberList.elems ; }\n  my List $returnList = (@numberList[0..$idx-1], @numberList[$idx..*]) ;\n  $returnList ;\n  } # end sub span\n\nsub MAIN()\n  {\n  say span( { $_ == 0 }, [2, 2, 5, 7, 4, 0] ) ;  #  (() (2 2 5 7 4 0))\n  say span( { $_ <  6 }, (2, 2, 5, 7, 4, 0) ) ;  #  ((2 2 5) (7 4 0))\n  say span( { $_ != 9 }, [2, 2, 5, 7, 4, 0] ) ;  #  ((2 2 5 7 4 0) ())\n  } # end sub MAIN\n
Run Code Online (Sandbox Code Playgroud)\n
\n

che*_*nyf 19

我使用first方法和:k副词,如下所示:

my @num  = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4];
my $idx = @num.first(* > 10):k;

@num[0..$idx-1], @num[$idx..*];
Run Code Online (Sandbox Code Playgroud)