In Raku, how does one write the equivalent of Haskell's span
function?
In Haskell, given a predicate and a list, one can split the list into two parts:
- the longest prefix of elements satisfying the predicate
- the remainder of the list
For example, the Haskell expression …
span (< 10) [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4]
… evaluates to …
([2,2,2,5,5,7],[13,9,6,2,20,4])
How does one write the Raku equivalent of Haskell's span
function?
Update 1
Based on the answer of @chenyf, I developed the following span
subroutine (additional later update reflects negated predicate within span
required to remain faithful to the positive logic of Haskell's span
function) …
sub span( &predicate, @numberList )
{
my &negatedPredicate = { ! &predicate($^x) } ;
my $idx = @numberList.first(&negatedPredicate):k ;
my @lst is Array[List] = @numberList[0..$idx-1], @numberList[$idx..*] ;
@lst ;
} # end sub span
sub MAIN()
{
my &myPredicate = { $_ <= 10 } ;
my @myNumberList is Array[Int] = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4] ;
my @result is Array[List] = span( &myPredicate, @myNumberList ) ;
say '@result is ...' ;
say @result ;
say '@result[0] is ...' ;
say @result[0] ;
say @result[0].WHAT ;
say '@result[1] is ...' ;
say @result[1] ;
say @result[1].WHAT ;
} # end sub MAIN
Program output is …
@result is ...
[(2 2 2 5 5 7) (13 9 6 2 20 4)]
@result[0] is ...
(2 2 2 5 5 7)
(List)
@result[1] is ...
(13 9 6 2 20 4)
(List)
Update 2
Utilizing information posted to StackOverflow concerning Raku's Nil
, the following updated draft of subroutine span
is …
sub span( &predicate, @numberList )
{
my &negatedPredicate = { ! &predicate($^x) } ;
my $idx = @numberList.first( &negatedPredicate ):k ;
if Nil ~~ any($idx) { $idx = @numberList.elems ; }
my List $returnList = (@numberList[0..$idx-1], @numberList[$idx..*]) ;
$returnList ;
} # end sub span
sub MAIN()
{
say span( { $_ == 0 }, [2, 2, 5, 7, 4, 0] ) ; # (() (2 2 5 7 4 0))
say span( { $_ < 6 }, (2, 2, 5, 7, 4, 0) ) ; # ((2 2 5) (7 4 0))
say span( { $_ != 9 }, [2, 2, 5, 7, 4, 0] ) ; # ((2 2 5 7 4 0) ())
} # end sub MAIN