pad*_*pad 8 f# list-comprehension list
我来自SML背景,对高阶函数感觉很舒服.但我真的不明白列表理解.是否存在列表理解比高阶函数更合适的情况,List反之亦然?
我听说列表理解比高阶函数慢,我应该避免在编写性能关键函数时使用它吗?
为了示例,请查看在F#中有效地投影列表列表,其中@cfern的答案分别包含使用列表推导和高阶函数的两个版本:
let rec cartesian = function
| [] -> [[]]
| L::Ls -> [for C in cartesian Ls do yield! [for x in L do yield x::C]]
Run Code Online (Sandbox Code Playgroud)
和:
let rec cartesian2 = function
| [] -> [[]]
| L::Ls -> cartesian2 Ls |> List.collect (fun C -> L |> List.map (fun x->x::C))
Run Code Online (Sandbox Code Playgroud)
Tom*_*cek 11
在理解和高阶函数之间进行选择主要是风格问题.我认为理解有时更具可读性,但这只是个人偏好.请注意,该cartesian函数可以更优雅地编写如下:
let rec cartesian = function
| [] -> [[]]
| L::Ls ->
[ for C in cartesian Ls do for x in L do yield x::C ]
Run Code Online (Sandbox Code Playgroud)
有趣的情况是编写递归函数.如果使用序列(和序列推导),它们会删除一些不必要的临时列表分配,如果yield!在尾部调用位置使用,还可以避免堆栈溢出异常:
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
Run Code Online (Sandbox Code Playgroud)
这是一个非常有趣的模式,因为它不能使用列表以相同的方式编写.使用列表时,您不能返回某个元素然后进行递归调用,因为它对应于n::(nums ...),而不是尾递归.
| 归档时间: |
|
| 查看次数: |
1055 次 |
| 最近记录: |