2009-07-29 3 views
11

Das Google liefert viele Beispiele für das Hinzufügen und Löschen von Einträgen in einem F # Wörterbuch (oder einer anderen Sammlung). Aber ich sehe nicht, Beispiele auf das Äquivalent vonWie deklarieren Sie die Werte eines Wörterbucheintrags als veränderbar?

myDict["Key"] = MyValue; 

Ich habe versucht

myDict.["Key"] <- MyValue 

ich auch das Wörterbuch zu erklären versucht haben, als

Dictionary<string, mutable string> 

auch mehrere Varianten auf Dies. Allerdings habe ich noch nicht auf die richtige Kombination getroffen ... wenn es in F # eigentlich möglich ist.

Edit: Der säumige Code ist:

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) 

Der Fehler, den ich habe, ist immer:

System.NotSupportedException: This value may not be mutated 
    at [email protected]_Item(K key, V value) 
    at <StartupCode$FSI_0036>[email protected](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>[email protected]() 
stopped due to error 

Antwort

24

f # hat zwei gemeinsame assoziative Datenstrukturen:

Die Sie am meisten verwendet werden, um die veränderbare Wörterbuch, die es erbt das ist es Präsenz im BCL ist und verwendet eine Hash-Tabelle unter der Haube.

let dict = new System.Collections.Generic.Dictionary<string,int>() 
dict.["everything"] <- 42 

Das andere als Map bekannt ist, und ist, gemeinsam funktionalen Stil, unveränderlich und mit Binärbäumen umgesetzt.

Anstelle von Operationen, die ein Dictionary ändern würden, stellen Maps Operationen bereit, die eine neue Map zurückgeben, die das Ergebnis der gewünschten Änderung ist. In vielen Fällen ist es unter der Haube nicht notwendig, eine komplett neue Kopie der gesamten Karte zu erstellen, so dass die Teile, die normalerweise geteilt werden können, sind. Zum Beispiel:

let withDouglasAdams = Map.add "everything" 42 Map.empty 

Der Wert withDouglasAdams wird für immer bleiben als eine Vereinigung von „alles“ zu 42. Wenn Sie also später tun:

let soLong = Map.remove "everything" withDouglasAdams 

Dann wird die Wirkung dieser ‚Entfernung‘ ist nur sichtbar, über den soLong Wert.

F # 's Map ist, wie erwähnt, als Binärbaum implementiert. Nachschlagen ist daher O (log n), während ein (gut erzogenes) Wörterbuch O (1) sein sollte. In der Praxis wird ein auf Hashes basierendes Wörterbuch dazu tendieren, die baumbasierte in fast allen einfachen (niedrige Anzahl von Elementen, geringe Wahrscheinlichkeit einer Kollision) zu übertreffen, da dies üblicherweise verwendet wird. Das heißt, der unveränderliche Aspekt der Map könnte es Ihnen ermöglichen, ihn in Situationen zu verwenden, in denen das Wörterbuch stattdessen komplexere Sperren erfordert oder mehr "eleganten" Code mit weniger Nebenwirkungen schreibt und somit eine sinnvolle Alternative bleibt.

Dies ist jedoch nicht die Quelle Ihres Problems.Das dict 'operator' gibt eine unveränderliche Implementierung IDictionary<K,T> zurück (obwohl dies in der Dokumentation nicht angegeben ist).

Von fslib-extra-pervasives.fs (beachten Sie auch die Verwendung von Optionen auf den Tasten):

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")) 
    ... 
+0

die Forschung Websites Verfügbarkeit ist wirklich ziemlich arm. Hier ist der Google-Cache-Link vorübergehend http://209.85.229.132/search?q=cache:GGIlRD9kBnYJ:research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp.core/microsoft.fsharp. collections.map.html + f% 23 + microsoft.fsharp.collections.map & cd = 1 & hl = de & ct = clnk & gl = uk – ShuggyCoUk

+3

Beachten Sie, dass die Suche in einem binären Baum wie angegeben O (log n) und nicht O (n log n) ist. – kvb

+0

oops - Tippfehler – ShuggyCoUk

5

Welche Fehler bekommen Sie? Ich habe versucht, die folgenden und kompiliert es ganz gut

let map = new System.Collections.Generic.Dictionary<string,int>() 
map.["foo"] <- 42 

EDIT Stellen Sie sicher, dass dieser Code nur fein wie gut lief.

+0

Interessant ... Ich habe gerade Karte [ "foo"] <-. 42 ;; Karte ["foo"] <- 43 ;; OK – telesphore4

+0

Vielleicht ist es etwas anderes ... Ich würde den Beitrag löschen, aber ich kann nicht – telesphore4

Verwandte Themen