Deep Get / Set
Als Ergänzung zu "Get - Set - Pull - Put" wird hier nun auf die "Deep-Funktionalität" eingegangen.
"Deep" bezeichnet in diesem Fall die Möglichkeit, mit einer einzigen "get/set/pull/put"-Funktion tief in Datenstrukturen einzugreifen.
Diese Funktionalität wurde vor allem für Bäume (Tree) entwickelt, lässt sich aber auch für viele weitere Bereiche verwenden.
Allen folgenden Funktionen gemein ist, dass ein Pfad an Positionen oder Schlüsseln verwendet wird.
Nachfolgend werden die vier Funktionen "get", "pull", "set" und "put" erklärt. Am mächtigsten ist hierbei "put", mit der eine komplexe Datenstruktur sehr schnell aufgebaut werden kann.
Deep Get
Hier als Beispiel eine ineinander verschachtelte Liste:
l = [ [3,7], [2,8], [1,9] ]
Soll nun auf die Position zugegriffen werden, an der die Zahl 7 liegt, so ist dies klassisch mit "get" möglich:
l.get( 1 ).get ( 2 ).print
Kürzer ist der Zugriff mit eckigen Klammern:
l[1][2].print
Und hier kommt nun die "Deep"-Funktionalität ins Spiel. Die Abfragen lassen sich zusammenführen:
l.get( 1, 2 ).print
bzw.:
l[1,2].print
Dies lässt sich sogar übergreifend über verschiedene Datenstrukturen anwenden:
l = [ ["abc", "def", "ghi"], ["jkl", "mno", "pqr"], ["stu", "vwx", "yz0"] ]
l[2,3,1].print
Somit wird in diesem Beispiel 'p' ausgegeben.
Zugriff auf eine Tabelle
Table-Objekte sind nach Zeilen und Spalten sortiert. So lässt sich mit "tabelle[zeile,spalte]" auf ein spezielles Element zugreifen. Liegt an dieser Stelle nun z.B. eine Liste, so kann ebenso in diese Liste hinein gegriffen werden:
t = Table( 2 )
t.add( [11,12], [13,14] ).add( [21,22], [23,24] )
t.print
t[2,1,2].print
Zugriff auf einen Baum
b = Tree
b.add("Foo", 5).add("Bar", 6).add("Bak", 7)
b.show
b["Foo", "Bar", "Bak"].print
Pull
"Pull" ist die "lazy" Variante von get.
Während "get" einen Fehler wirft, gibt "pull" ggf. "nil" zurück, sollte das gewünschte Element außerhalb der Datenstruktur liegen.
[].pull(3,6,2).print
Set
Mit "set" wird ein Objekt an eine bestimmte Stelle in einer Datenstruktur gesetzt.
Die zu übergebenden Argumente sind dabei:
Objekt, position1, position2, position3, ...
Man könnte dies lesen als: "Setze Objekt XY nach AB,CD,EF. Der angegebene Pfad muss allerdings bestehen, ansonsten wird ein Fehler geworfen.
Liste
l = [ ['a','b'], ['c','d'] ]
l.set( 'x', 2, 1 )
l.print
Tabelle
Das Table-Objekt ist nach Zeile/Spalte aufgebaut.
t = Table(2).add('a','b').add('c','d')
t.print
t.set('x', 2, 1)
t.set('y', 1, 2)
t.print
Kurzform
Die Kurzform von "set" sind eckige Klammern, gefolgt von einem "=".
t = Table(2).add('a','b').add('c','d')
t[2,1] = 'x'
t[1,2] = 'y'
t.print
Put
Dies ist die wichtigste und mächtigste Deep-Funktion. Während "set" einen Fehler wirft, sollte der angegebene Pfad nicht gesetzt werden können, wird "put" ggf. die Struktur so erweitern, dass das Objekt wie gewünscht an die entsprechende Position gesetzt werden kann.
In der Kurzform wird, wie bei "pull", an die eckigen Klammern ein Fragezeichen angefügt.
Liste
[].put('a', 5).print
Hier ist das Ergebnis:
[nil,nil,nil,nil,a]
Dies kann nun auch mehrdimensional verwendet werden:
[].put('a', 2, 2, 2).print
Hier soll das Objekt 'a' an Position 2,2,2 abgelegt werden. Das Ergebnis ist eine verschachtelte Liste:
[nil,[nil,[nil,a]]]
Die Kurzform wäre in diesem Fall:
l = []
l[2,2,2]? = 4
l.print
Baum
Besonders interessant wird dies bei einer Baumstruktur.
t = Tree
t["Foo","Bar","Bak"]? = 5
t.show
Hier wird die entsprechende Baumstruktur so erstellt, dass der Wert 5 an der gewünschten Stelle gesetzt werden kann. So lässt sich schnell auch eine komplexere Baumstruktur erstellen:
t = Tree
t["ab","cd","ef","gh"]? = 1
t["ab","cd","ij","kl"]? = 2
t["ab","mn","op","qr"]? = 3
t["st","uv"]? = 4
t["ab","mn","wx","yz"]? = 5
t.show
VarArgs
Übrigens, in allen vorherigen Funktionen wird der Pfad als "VarArgs" übergeben.
Entsprechend lässt sich der Pfad auch direkt als Liste übergeben:
path1 = ["foo","bar","bak"]
path2 = ["foo","boo","tak"]
t = Tree
t.put( 2, :path1 )
t.show
t[:path2]? = 3
t.show
Der Doppelpunkt signalisiert dabei, dass nicht der Inhalt der Variable, sondern die Variable selbst (als VarLet) übergeben werden soll.