F#在KeyNotFoundException中为map结果添加值

Sli*_*ipe 3 f#

type bytesLookup = Map<byte,int list>
type lookupList = bytesLookup list

let maps:bytesLookup = Map.empty

let printArg arg = printfn(Printf.TextWriterFormat<unit>(arg))

let array1 = [|byte(0x02);byte(0xB1);byte(0xA3);byte(0x02);byte(0x18);byte(0x2F)|]

let InitializeNew(maps:bytesLookup,element,index) =
    maps.Add(element,List.empty<int>)(*KeyNotFoundException*)
    maps.[element]

let MapArray (arr:byte[],maps:bytesLookup ) =
   for i in 0..arr.Length do
       match maps.TryFind(arr.[i]) with
        | Some(e) -> i::e
        | None -> InitializeNew(maps,arr.[i],i)

MapArray(array1,maps);

printArg( maps.Count.ToString())
Run Code Online (Sandbox Code Playgroud)

例外

System.Collections.Generic.KeyNotFoundException:给定的键不在字典中.在Microsoft.FSharp.Collections.MapTreeModule.find [TValue,a](IComparer 1 comparer, TValue k, MapTree2 m),2.get_Item(TKey key) at FSI_0012.MapArray(Byte[] arr, FSharpMap位于Script1.fsx 中的Microsoft.FSharp.Collections.FSharpMap 2 maps):第16行,位于Script1中的.$ FSI_0012.main @(). fsx:第20行

在函数中,我正在尝试使用int列表初始化地图中的新元素.我还尝试将新的int值同时推送到列表中.

我究竟做错了什么?

The*_*ght 6

F#Map是一个不可变的数据结构,该Add方法不会修改现有的数据结构,它会返回一个Map带有您请求的新增内容的新结构.

注意:

let ex1 = 
    let maps = Map.empty<byte, int list>
    maps.Add(1uy, [1]) // compiler warning here!
    maps.[1uy]
Run Code Online (Sandbox Code Playgroud)

关于这段代码的两件事:

  1. System.Collections.Generic.KeyNotFoundException当你运行它时它会抛出

  2. 它为您提供编译器警告,该行maps.Add...应具有类型unit但实际上具有类型Map<byte,int list>.不要忽视警告!

现在试试这个:

let ex2 =
    let maps = Map.empty<byte, int list>
    let maps2 = maps.Add(1uy, [1])
    maps2.[1uy]
Run Code Online (Sandbox Code Playgroud)

没有警告.没有例外.代码按预期工作,返回值[1].