Wie funktioniert die Zuordnung zu einem Mapping?

Ich versuche zu verstehen, wie Mappings funktionieren. Ich habe so etwas noch nie zuvor gesehen, aber ich bin sicher, dass viele Sprachen etwas Ähnliches verwenden. Wie auch immer, hier ist mein Code:

Geben Sie hier die Bildbeschreibung ein

Was mache ich hier falsch?

Danke schön!

Antworten (3)

Der Grund für Ihren Fehler liegt darin, dass Sie in Solidität nur Deklarationen außerhalb von Funktionen haben können.

In Ihrem Code deklarieren Sie die Zuordnung und führen dann in einer anderen Operation eine Zuweisung durch, die nur in einer Funktion möglich ist.

Für die anderen Datentypen ist es möglich, die Zuweisung auch während der Initialisierung vorzunehmen, damit es funktioniert.

Zuordnungen können als Hash-Tabellen betrachtet werden, aber es ist anders. In solidity wird ein Mapping von Anfang an mit allen möglichen Schlüsseln initialisiert und der zugehörige Wert des Schlüssels ist der Standardwert für den angegebenen Typ. In Solidität können Sie Schlüsseln also nur neue Werte hinzufügen, und Sie können keine neuen Schlüssel hinzufügen, da sie bereits vorhanden sind.

Zu erwähnen ist auch, dass Sie standardmäßig nicht über eine Zuordnung in Solidity iterieren können. Das hängt wiederum mit dem zusammen, was ich zuvor geschrieben habe. Außerdem können Sie nicht nur die Schlüssel abrufen, für die Sie einige Werte eingerichtet haben, da Sie alle Schlüssel standardmäßig mit Werten eingerichtet haben.

Es gibt also keine Möglichkeit, über eine Zuordnung zu summieren? Wenn ich die Summe wissen möchte, muss ich sie in einer zusätzlichen Variablen speichern oder überhaupt ein Array verwenden?
Dein erster Satz ist irrelevant.
@AndiGiga @AndiGiga Das ist richtig. Zuordnungen wandeln den Schlüssel einfach in eine Struktur vom Typ um ValueType.
@JossieCalderon warum ist mein erster Satz irrelevant?
@dragosb Die Antwort lautet, weil Zuweisungen für deklarierte Variablen außerhalb von Funktionen nicht zulässig sind. Nicht, weil Sie nur Deklarationen außerhalb von Funktionen haben können, obwohl das auch stimmt.

Mappings sind nur am Rande wie Hash-Tabellen und werden völlig anders als jede andere Programmiersprache implementiert. Typischerweise hat eine Hash-Tabelle ein internes Array, das zu 25-75 % mit Schlüsseln/Werten gefüllt ist, die Sie gespeichert haben. Und Sie können darüber iterieren, da Sie in einer nicht-trivialen Tabelle nur höchstens 75 % leere Zellen überspringen. Unterschiede bei Solidity-Mappings:

  • Anstelle einer kleinen internen Tabelle (normalerweise ab Größe 16) zum Speichern von Schlüssel/Wert-Paaren verwendet das Mapping von Solidity den gesamten 256-Bit-adressierbaren Speicherplatz. Eine Iteration ist also rechnerisch nicht machbar.
  • Anstatt auf eine verknüpfte Liste von Schlüssel/Wert-Paaren zu verweisen, speichern Solidity-Mappings den Schlüssel überhaupt nicht, führen keinerlei Kollisionserkennung durch und speichern keine Zeiger auf die Werte, sondern speichern den Wert direkt. (Deshalb können Sie den Schlüssel nicht wieder herausholen und können nicht erkennen, ob der Schlüssel gesetzt wurde oder nicht.)
  • Anstatt eine schnelle/unsichere Mersenne-Prime-basierte Hash-Funktion zu verwenden, verwendet es SHA3 und ordnet das Signal nicht einem kleineren Satz zu. (Deshalb muss es sich keine Gedanken über Kollisionen machen.)
  • Sie sind echte O(1)Operationen (aus dem POV des Skripts), nicht O(1+e)wie die meisten anderen Hash-Tabellen. Es gibt keine Long-Tail-Wachstumskosten, da sich der Tisch niemals ausdehnt und keine O(n)Kollisionskette läuft.

Daher würde ich empfehlen, sie NICHT als Hash-Tabellen zu betrachten. Betrachten Sie sie stattdessen nur als Einwegfunktionen , die einen Zeiger auf eine pseudozufällige Speicheradresse zurückgeben.

Ich hatte angenommen, dass sie nur eine perfekte Hash-Funktion verwendet haben . Ist das nicht der Fall?
@RichardHorrocks nein. Es verwendet SHA3, was keine perfekte Hash-Funktion ist. Kollisionen sind in SHA3 möglich (auch wenn keine jemals demonstriert wurden), während sie es in einer perfekten Hash-Funktion nicht sind. Außerdem kann keine Hash-Funktion, die den möglichen Weltraum verkleinert, eine perfekte Hash-Funktion sein. (was SHA3 tut, schrumpft es von unendlich auf 2 ^ 256.)
Aha - danke für die Aufklärung meines Missverständnisses :-)
np. Aus der Sicht der realen Welt haben Sie jedoch funktional Recht. Da es in SHA3 keine bekannte Kollision gibt, ist es verdammt nah an einer perfekten Hash-Funktion. es als solches zu betrachten, ist keine schlechte Heuristik. :)

Um Mappings zu verstehen, können Sie sie als Hash-Tabellen sehen .

Über Ihren Code kann Ihnen wahrscheinlich jemand anderes eine vollständige Erklärung geben, aber ich denke, das liegt daran, dass Sie den Wert der Zuordnung innerhalb einer Funktion zuweisen müssen, zum Beispiel:

contract Complex{
    uint a = 1;
    uint b = 3;
    mapping(uint => uint) myMap;

    function Complex(){
        myMap[a] = b;
    }
}

Dieses Stück Code macht das Gleiche, fügt aber das myMap[a] = b;in den Konstruktor ein.