2017-02-22 57 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

並且在這裏添加不可變列表真的非常出色,並且在很多情況下擊敗了可變列表。 –

相關問題