简体   繁体   English

F# 中“不可变”列表的混淆

[英]Confusion on "Immutable" lists in F#

Totally newbie question.完全新手问题。

I'm still trying to get a grasp on "Immutable" lists in F#.我仍在尝试掌握 F# 中的“不可变”列表。

Lets assume I have a "Visit" defined as:让我们假设我有一个“访问”定义为:

module Visit =
    type Model =
        {
            Name: string
        }

    let init row col cel =
        { 
            Name = sprintf "My Name is row: %d col: %d  cel: %d" row  col cel       
        }

Now I define a "Cell" that may or may not have one visit:现在我定义了一个可能有也可能没有一次访问的“单元格”:

module Cell =
    type Model =
        {
            Visit: Visit.Model option
        }

    let setVisit m =
        { m with Visit = Some( Visit.init 9 9 9) }

and lastly I define a "Column" that has a list of cells:最后我定义了一个包含单元格列表的“列”:

module Column =
    type Model =
        {         
            Appointments: Cell.Model list
        }


    let updateCell (m:Model) =
        let newList = m.Appointments |> List.mapi (fun index cell -> if index = 2 then Cell.setVisit cell else cell)
        {m with Appointments = newList }

In the Column module, the "updateCell" function is wired to call Cell.setVisit for the 3rd cell.在 Column 模块中,“updateCell”函数被连接到为第三个单元格调用 Cell.setVisit。 My intent is to replace the "Name" of the "Visit" held by the 3rd cell.我的意图是替换第三个单元格持有的“访问”的“名称”。 My simple questions are:我的简单问题是:

  1. Is this the correct way to do this?这是正确的方法吗?
  2. If I am replacing the Appointments list, is this not changing the "Column" holding the Appointment List?如果我要替换约会列表,这是否不会更改保存约会列表的“列”? (The Column is immutable, right? ). (列是不可变的,对吧?)。

Sorry for my confusion.对不起,我的困惑。

TIA TIA

First : yes, this is an acceptable, if inefficient way of doing it for lists.第一:是的,这是一种可以接受但效率低下的列表方式。 Note that you're rebuilding the whole list on every updateCell call, even though most elements in it are the same.请注意,您在每次updateCell调用时都会重建整个列表,即使其中的大多数元素都相同。

I don't know how many appointments you expect to have in your model in practice.我不知道您在实践中希望在您的模型中有多少约会。 If it's significantly more than three, and if you're always updating the third one, it would be more efficient to cut the list, then glue it back together:如果它明显多于三个,并且您总是更新第三个,那么剪切列表会更有效,然后将其重新粘在一起:

let newList = List.take 2 m.Appointments @ [Cell.setVisit m.Appointments.[2]] @ List.drop 3 m.Appointments

This way only the first three elements are rebuilt, and the tail of the list is reused.这样只重建了前三个元素,并重用了列表的尾部。

However, if you need random-access operations, may I suggest using arrays instead?但是,如果您需要随机访问操作,我可以建议改用数组吗? Sure, they're mutable, but they offer much better performance for random-access operations.当然,它们是可变的,但它们为随机访问操作提供了更好的性能。

Second : no, the syntax { m with ... } does not change the Column .第二:不,语法{ m with ... }不会改变Column Instead, it creates a new column - a copy of m , but with all fields listed after with updated to new values.相反,它会创建一个列 - m的副本,但所有字段都列在后面with更新为新值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM