2017-02-22 8 views
3

Внутри цикла Я добавляю новый элемент в список, который мне нужен в следующей итерации, потому что я использую переменную .Net List<T>.F #: Можно ли использовать изменяемый список .Net для добавления элементов в один список

F# рекомендует использовать неизменяемые коллекции в целом, и кажется, что я не могу достичь того, что я хочу использовать неизменяемым list или seq.

Допустимо ли продолжать использовать изменчивый .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

«Приемлемый» очень субъективен. Сказав это: приемлемо? Скорее всего. Необходимо? Скорее всего, нет. Быстрее использовать mutable? Не понятно. Если вы дадите больше контекста, вы получите лучшие ответы. Как вы строите список? Как вы его используете? –

+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. Это цель четко обозначена с комментариями, так что будущие сопровождающие не будут путешествовать по нему при рефакторинге кода (и неверно предполагая, что изменяемый объект является неизменным).

Это, безусловно, экономит много времени, которое нужно будет идти в письменной форме правильный хвост рекурсивной fold для дерева (что, конечно, вариант, как хорошо, см this blog post series). И даже если вы закончите писать складку, это правильный выбор для прототипирования вашего подхода.

В качестве побочного примечания я предпочитаю использовать ref cells + неизменяемые коллекции, а не изменчивые коллекции для этой цели. Дополнительный синтаксис, необходимый для мутации ячейки ref, делает ее совершенно ясным, что происходит, в отличие от вызова Add в изменяемом списке.

+2

И добавить здесь, что неизменные списки действительно удивительно эффективны и избили измененный список в довольно многих случаях. –

Смежные вопросы