2017-02-22 24 views
3

在循环内我添加了一个新元素到列表中,我需要在下一次迭代中使用可变的.Net List<T>F#:是否可以使用可变.Net列表添加元素到同一个列表

F#鼓励在一般情况下使用不可变集合,并且似乎我无法实现我想要的使用immutable listseq

继续使用可变的.Net List<T>还是可以接受的,还是鼓励只使用不可变的?如果是的话,我怎么能实现呢?

我的代码是有点长而复杂,所以让我们考虑这个伪F#代码:

let children = new List<node>() 
let bestBranchEntropies = entropiesSuchAs data.Rows parents 
//Finding the best children for the best parent 
bestBranchEntropies |> Seq.iter (fun bestBranch -> let attribut = IGetTheAttributByMaximumGainHere 
                //Creating one of the children in every iteration 
                let node = { 
                   content = attribut; 
                   branch = Some(fst bestBranch); 
                   children = None; 
                   isLeaf = false; 
                   } 
                //Considering it a child 
                children.Add node 

           ) 
         //After having all the children 
         let children' = children |> Seq.map (fun child -> { 
                      content = child.content; 
                      branch = child.branch; 
                      children = //recursive call here to do the same work above (getting children again, yeah it's a tree) 
                      isLeaf = child.isLeaf; 
                      }) 

         Some(children') 
+2

“可接受”是非常主观的。话虽如此:可以接受吗?最有可能的。必要?很可能不会。更快使用可变吗?不清楚。如果你给更多的上下文,你会得到更好的答案。你如何建立清单?你怎么使用它? –

+0

F#具有可变列表类型的特殊类型缩写,因此可以使用它。 –

+0

几乎可以肯定地有一种不变的选择,如果你给我们提供了一些背景知识,我们可以解释一下。 – TheInnerLight

回答

4

据我所看到的,当然也不需要一个可变的列表(如果你的伪代码充分反映了这个问题)。考虑以下几点:

let children = 
    bestBranchEntropies 
    |> Seq.map (fun bestBranch -> 
     let attribut = IGetTheAttributByMaximumGainHere 
     //Creating one of the children in every iteration 
     { 
      content = attribut; 
      branch = Some(fst bestBranch); 
      children = None; 
      isLeaf = false; 
     } 
    |> Seq.toList 
children 
|> Seq.map (fun child -> 
    { 
     content = child.content 
     branch = child.branch 
     children = //recursive call here to do the same work above (getting children again, yeah it's a tree) 
     isLeaf = child.isLeaf 
    } 
) 
|> Some 

第一Seq.toList可以跳过,你可以通过使用管道一路。从你的伪代码看来,整个第二个循环实际上可以安全地与第一个循环合并?

+0

我想关于在第二个循环中递归调用的注释位是棘手的位。 – scrwtp

+0

可能 - 但我们只能在这里工作:-) –

3

从你的伪代码中不是很清楚,但我知道你所问的真正问题是“在遍历树结构时可以使用可变列表而不是累加器吗?”。

我会说这很好,但前提是:

  1. 的可变对象是本地的功能,否则无法访问和篡改,
  2. 它的目的显然与注释标记,所以当重构代码时(并且错误地假定可变对象是不可变的),未来的维护者不会在其上跳动。

这无疑节省了大量的时间,将需要进入写一个适当的尾递归你的树(这当然是一个选项,以及,见this blog post seriesfold。即使你最终写了一个折叠,这也是你首先对你的方法进行原型设计的公平选择。

作为一个方面说明,我更喜欢使用ref cells +不可变集合而不是可变集合来实现此目的。变异引用单元所需的额外语法使得它清楚地知道发生了什么,而不是在可变列表上调用Add

+2

并且在这里添加不可变列表真的非常出色,并且在很多情况下击败了可变列表。 –

相关问题