简体   繁体   中英

Confusion on "Immutable" lists in F#

Totally newbie question.

I'm still trying to get a grasp on "Immutable" lists in 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. 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

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.

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 . Instead, it creates a new column - a copy of m , but with all fields listed after with updated to new values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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