Google提供了大量在F#字典(或其他集合)中添加和删除条目的示例。但我没有看到相当于
的例子myDict["Key"] = MyValue;
我试过
myDict.["Key"] <- MyValue
我还尝试将字典声明为
Dictionary<string, mutable string>
还有几个变种。但是,我还没有找到正确的组合...如果 实际上可以在F#中使用。
编辑:违规代码是:
type Config(?fileName : string) =
let fileName = defaultArg fileName @"C:\path\myConfigs.ini"
static let settings =
dict[ "Setting1", "1";
"Setting2", "2";
"Debug", "0";
"State", "Disarray";]
let settingRegex = new Regex(@"\s*(?<key>([^;#=]*[^;#= ]))\s*=\s*(?<value>([^;#]*[^;# ]))")
do File.ReadAllLines(fileName)
|> Seq.map(fun line -> settingRegex.Match(line))
|> Seq.filter(fun mtch -> mtch.Success)
|> Seq.iter(fun mtch -> settings.[mtch.Groups.Item("key").Value] <- mtch.Groups.Item("value").Value)
我得到的错误是:
System.NotSupportedException: This value may not be mutated
at Microsoft.FSharp.Core.ExtraTopLevelOperators.dict@37-2.set_Item(K key, V value)
at <StartupCode$FSI_0036>.$FSI_0036_Config.$ctor@25-6.Invoke(Match mtch)
at Microsoft.FSharp.Collections.SeqModule.iter[T](FastFunc`2 action, IEnumerable`1 sequence)
at FSI_0036.Utilities.Config..ctor(Option`1 fileName)
at <StartupCode$FSI_0041>.$FSI_0041.main@()
stopped due to error
答案 0 :(得分:27)
f#有两种常见的关联数据结构:
你最习惯的那个,它继承的可变字典是它在BCL中的存在并且在引擎盖下使用哈希表。
let dict = new System.Collections.Generic.Dictionary<string,int>()
dict.["everything"] <- 42
另一个被称为Map,并且是通用的函数式,是不可变的,并用二叉树实现。
映射提供了返回新映射的操作,而不是可以更改字典的操作,而映射是请求的任何更改的结果。在许多情况下,在引擎盖下,不需要制作整个地图的全新副本,因此可以正常共享的那些部分是。例如:
let withDouglasAdams = Map.add "everything" 42 Map.empty
值withDouglasAdams
将永远保留为“所有”与42的关联。所以,如果您以后这样做:
let soLong = Map.remove "everything" withDouglasAdams
然后,只有soLong
值才能看到此“删除”的效果。
然而,这不是您问题的根源。 dict'operator'返回一个明确的不可变IDictionary<K,T>
实现(尽管在它的文档中没有说明这一点)。
来自 fslib-extra-pervasives.fs (另请注意在键上使用选项):
let dict l =
// Use a dictionary (this requires hashing and equality on the key type)
// Wrap keys in an Some(_) option in case they are null
// (when System.Collections.Generic.Dictionary fails). Sad but true.
let t = new Dictionary<Option<_>,_>(HashIdentity.Structural)
for (k,v) in l do
t.[Some(k)] <- v
let d = (t :> IDictionary<_,_>)
let c = (t :> ICollection<_>)
let ieg = (t :> IEnumerable<_>)
let ie = (t :> System.Collections.IEnumerable)
// Give a read-only view of the dictionary
{ new IDictionary<'key, 'a> with
member s.Item
with get x = d.[Some(x)]
and set (x,v) = raise (NotSupportedException(
"This value may not be mutated"))
...
答案 1 :(得分:5)
你得到什么错误?我尝试了以下内容,它编译得很好
let map = new System.Collections.Generic.Dictionary<string,int>()
map.["foo"] <- 42
编辑验证此代码运行正常。