Linked list partition function and reversed results

前端 未结 5 731
耶瑟儿~
耶瑟儿~ 2020-12-02 00:26

I wrote this F# function to partition a list up to a certain point and no further -- much like a cross between takeWhile and partition.

<         


        
5条回答
  •  不知归路
    2020-12-02 00:53

    I don't think I'm the only one to learn a lot from (struggling with) Daniel's CPS solution. In trying to figure it out, it helped me change several potentially (to the beginner) ambiguous list references, like so:

        let partitionWhileCps cond l1 =
    
            let rec aux f l2 = 
                match l2 with
                | h::t when cond h ->   aux  (fun (acc, l3) -> f (h::acc, l3))  t
                | l4 -> f ([], l4)
    
            aux id l1
    

    (Note that "[]" in the l4 match is the initial acc value.) I like this solution because it feels less kludgey not having to use List.rev, by drilling to the end of the first list and building the second list backwards. I think the other main way to avoid .rev would be to use tail recursion with a cons operation. Some languages optimize "tail recursion mod cons" in the same way as proper tail recursion (but Don Syme has said that this won't be coming to F#).

    So this is not tail-recursive safe in F#, but it makes my answer an answer and avoids List.rev (this is ugly to have to access the two tuple elements and would be a more fitting parallel to the cps approach otherwise, I think, like if we only returned the first list):

        let partitionWhileTrmc cond l1 = 
    
            let rec aux acc l2 =  
                match l2 with 
                | h::t when cond h ->  ( h::fst(aux acc t), snd(aux acc t)) 
                | l3 -> (acc, l3)
    
            aux [] l1
    

提交回复
热议问题