List comprehension vs high-order functions in F#

后端 未结 3 1252
星月不相逢
星月不相逢 2021-02-09 02:31

I come from SML background and feel quite comfortable with high-order functions. But I don\'t really get the idea of list comprehension. Is there any situation where list co

3条回答
  •  醉酒成梦
    2021-02-09 03:03

    Choosing between comprehensions and higher-order functions is mostly a matter of style. I think that comprehensions are sometimes more readable, but that's just a personal preference. Note that the cartesian function could be written more elegantly like this:

    let rec cartesian = function  
      | [] -> [[]]  
      | L::Ls -> 
         [ for C in cartesian Ls do for x in L do yield x::C ]
    

    The interesting case is when writing recursive functions. If you use sequences (and sequence comprehensions), they remove some unnecessary allocation of temporary lists and if you use yield! in a tail-call position, you can also avoid stack overflow exceptions:

    let rec nums n = 
      if n = 100000 then []
      else n::(nums (n+1))
    // throws StackOverflowException
    nums 0 
    
    let rec nums n = seq {
      if n < 100000 then
        yield n
        yield! nums (n+1) }
    // works just fine
    nums 0 |> List.ofSeq 
    

    This is quite an interesting pattern, because it cannot be written in the same way using lists. When using lists, you cannot return some element and then make a recursive call, because it corresponds to n::(nums ...), which is not tail-recursive.

提交回复
热议问题