【发布时间】:2021-08-13 03:38:40
【问题描述】:
我遇到了一个递归函数的问题,该函数在较大的数据集上遇到堆栈溢出,因此我尝试重写该函数以使用连续递归,但如果说我是新手,那就太轻描淡写了。在下面的示例中,第一个函数 processList 在小数据集上给出了所需的结果。第二个函数 processListCont 似乎可以工作,但是我知道肯定有一个错误,因为当我通过它运行相同的小数据集时,我得到了不同的结果。 processListCont 是表达 processList 函数的正确方法还是我遗漏了什么?
open System
type Something(id) =
member val id = id with get, set
member val children : list<Something> = [] with get, set
member val processed : bool = false with get, set
let rec processList (item:Something, itemList:list<Something>) =
for child in item.children do
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
processList(parent, itemList)
let processListCont (item:Something, itemList:list<Something>) =
let rec _processListCont (item:Something, itemList:list<Something>, f) =
for child in item.children do
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
f(parent, itemList)
_processListCont(item, itemList, (fun (item:Something, itemList:list<Something>) -> ()))
[<EntryPoint>]
let main argv =
// generate some data
let count = 10000
let idList = List.init count (fun index -> index)
let items = [for (id) in idList -> Something id]
let rnd = System.Random()
for i in items do
i.children <- List.init 100 (fun _ -> Something (rnd.Next(0, count - 1)))
// process the list
for i in items do
processList(i, items)
Console.WriteLine("Processing completed successfully")
Console.ReadKey()
|> ignore
0
【问题讨论】:
-
有一些问题使得很难将 CPS 应用到这个特定的设计中:1) 当每个树节点有固定数量的子节点,但你的节点有可变数量时,CPS 更容易理解. 2) CPS 在纯函数上下文中更容易理解,但您的代码是命令式的:处理节点会在节点的父节点中产生副作用。如果您愿意考虑不同的设计,this presentation 中标有“另一个示例”的幻灯片可能对您有所帮助。
标签: recursion f# continuation-passing