这里有一种使用可变列表(ref-cells)票据的方法:
let maxSeats = 10
let tickets : (int * Ticket option) ref list =
[1..maxSeats]
|> List.map (fun s -> ref (s, None) )
let bookSeat seat name =
match List.tryFind (fun r -> let (s,_) = !r in s = seat) tickets with
| Some r ->
r :=
match !r with
| (s, Some ticket) -> (s, Some { ticket with customer = name })
| (s, None) -> (s, Some { seat = s; customer = name })
| None ->
failwith "seat not found"
显而易见的是,如果您想要添加座位而不是用所有明显的座位初始化它们,您也可以使tickets
本身可变。
更好的方法(?)
尽管如此,我认为这样做是错误的方式-我认为您需要一个Map:
type Ticket = {seat:int; customer:string}
type Tickets = Map<int, Ticket>
let bookSeat seat name (tickets : Tickets) =
match Map.tryFind seat tickets with
| Some oldTicket ->
tickets
|> Map.remove seat
|> Map.add seat { oldTicket with customer = name }
| None ->
tickets
|> Map.add seat { seat = seat; customer = name }
请注意,这些都是不可变的值,因此
bookSeat
将返回一个新的
Ticket
-reservation-map
使用Dictionary
混合
或者您可以使用常见的 .net
Dictionary
并进行突变:
type Ticket = {seat:int; customer:string}
let tickets = System.Collections.Generic.Dictionary<int, Ticket>()
let bookSeat seat name =
match tickets.TryGetValue seat with
| (true, oldTicket) ->
tickets.[seat] <- { oldTicket with customer = name }
| (false, _) ->
tickets.[seat] <- { seat = seat; customer = name }
在这里,您不必在Tickets
之间传递 - 它们将在原地改变(但是Ticket
对象本身仍然是不可变的)
请注意,目前这不是线程安全的,所以要小心。
System.Collection.Generic.List<'t>
,就像你可能在 C# 中使用的一样 - 然后你可以用let oldTicket = list.[itemNr]
来获取旧票据,使用let newTicket = { oldTicket with customer = "newCustomerName" }
创建一个新记录,并使用list.[itemNr] <- newTicket
将其放回列表中。 - Random Dev