Wie Sie vermutlich schon herausgefunden haben, erlaubt Vim nicht, dass List- oder Dictionary-Variablen als Wörterbuchschlüssel verwendet werden. Das bedeutet, dass Sie zum Beispiel ein "geprüftes" Wörterbuch nicht wie dieses auffüllen können:
" Unless k is a String, this won't work.
:let checked[k] = 1
Es gibt auch keine einfache Möglichkeit, eine eindeutige Zeichenkette aus einer Liste oder einem Wörterbuch zu erzeugen, so dass auch dies nicht zuverlässig ist:
:let checked[ string(k) ] = 1
Ein besserer Ansatz ist es, die Datenstrukturen selbst zu markieren, anstatt zu versuchen, eine Hashtabelle zu erstellen. Wenn es Ihnen nichts ausmacht, Ihre Datenstrukturen vorübergehend schreibgeschützt zu machen, ist eine Möglichkeit, dies zu tun, die Verwendung von :lockvar
:
:let someDict = {}
:let someDict['foo'] = [1, 2, 3]
:lockvar 1 someDict
Das markiert someDict
als schreibgeschützt. (Die 1
beschränkt das Sperren auf die oberste Ebene des Dictionarys, so dass verschachtelte Strukturen nicht automatisch gesperrt werden). Der Sperrstatus einer Variablen kann wie folgt überprüft werden:
:echo islocked('someDict')
1
:echo islocked("someDict['foo']")
0
:echo islocked("someDict['foo'][0]")
0
Das Entriegeln ist ebenso einfach:
:unlockvar 1 someDict
Jetzt haben wir also eine Technik, um einzelne Ebenen von verschachtelten Datenstrukturen als "geprüft" zu markieren, eine Möglichkeit, abzufragen, ob eine bestimmte Ebene markiert ist oder nicht, und eine Möglichkeit, alle Markierungen zu entfernen, wenn wir fertig sind. Das Ganze zusammenfügen, AlreadyChecked()
kann wie folgt geändert werden:
function! s:AlreadyChecked(arg, checkedlst)
if type(a:arg)!=type([]) && type(a:arg)!=type({})
return 0
endif
" If this particular List or Dictionary has already been checked, just
" return true immediately.
"
if islocked('a:arg')
echo "Already checked."
return 1
endif
" Lock the List or Dictionary to mark this item as already
" checked. Note that only the top level of the List or Dictionary
" is locked; values are not locked.
"
lockvar 1 a:arg
" Remember everything we've locked, so it can be unlocked once
" we're done.
"
call add(a:checkedlst, a:arg)
return 0
endfunction
Wenn Sie mit der Kontrolle fertig sind, entfernen Sie einfach alle Schlösser:
for obj in a:checkedlst
unlockvar 1 obj
endfor
Ich hoffe, das hilft. Es ist ein hackish Missbrauch der Sperrfunktion, aber vielleicht wird es tun, was Sie brauchen.