I have a script that is intended to check whether some value (e.g. option or function argument) matches some model. I want my script to be able to check recursive data structures. So the question is: is there more efficient way then iterating over some list that contains references to already checked Lists and Dictionaries. Example code:
function s:AlreadyChecked(arg, checkedlst)
if type(a:arg)!=type([]) && type(a:arg)!=type({})
return 0
endif
for obj in a:checkedlst
if a:arg is obj
return 1
endif
endfor
call add(a:checkedlst, a:arg)
return 0
endfunction
Seeking for a way to sort checkedlst (that is to compare references, but not values found by them) or even to use a hash.
As I’m guessing you’ve already discovered, Vim doesn’t allow List or Dictionary variables to be used as dictionary keys. That means you can’t, for example, populate a “checked” dictionary like this:
It also lacks a straightforward way to generate a unique String from a List or Dictionary, so this isn’t reliable either:
A better approach is to mark the data structures themselves instead of trying to build a hashtable. If you don’t mind temporarily making your data structures read-only, one way to do that is to use
:lockvar:That marks
someDictas read-only. (The1limits the locking to the top level of the Dictionary, so nested structures aren’t automatically locked.) A variable’s lock state can be inspected like this:Unlocking is just as easy:
So now we have a technique for marking individual levels of nested data structures as “checked”, a way to query whether or not a particular level is marked, and a way to remove all the marks when we’re done. Putting it all together,
AlreadyChecked()can be modified like so:Once you’re done checking, just remove all the locks:
Hope this helps. It’s a hackish abuse of the locking facility, but perhaps it will do what you need.