Как я полагаю, вы уже обнаружили, Vim не позволяет использовать переменные List или Dictionary в качестве словарных ключей.Это означает, что вы не можете, например, заполнить «проверенный» словарь следующим образом:
" Unless k is a String, this won't work.
:let checked[k] = 1
Также не хватает простого способа генерировать уникальную строку из списка или словаря, так что это не так.либо надежный:
:let checked[ string(k) ] = 1
Лучшим подходом является пометка самих структур данных, а не попытка создать хеш-таблицу.Если вы не против временно сделать ваши структуры данных доступными только для чтения, один из способов сделать это - использовать :lockvar
:
:let someDict = {}
:let someDict['foo'] = [1, 2, 3]
:lockvar 1 someDict
, который помечает someDict
только для чтения.(1
ограничивает блокировку верхним уровнем словаря, поэтому вложенные структуры не блокируются автоматически.) Состояние блокировки переменной можно проверить следующим образом:
:echo islocked('someDict')
1
:echo islocked("someDict['foo']")
0
:echo islocked("someDict['foo'][0]")
0
Разблокировка также проста:
:unlockvar 1 someDict
Итак, теперь у нас есть метод для обозначения отдельных уровней вложенных структур данных как «проверенных», способ запрашивать, помечен ли определенный уровень или нет, и способ удалить все отметкикогда мы закончимСобрав все это вместе, AlreadyChecked()
можно изменить следующим образом:
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
Как только вы закончите проверку, просто удалите все блокировки:
for obj in a:checkedlst
unlockvar 1 obj
endfor
Надеюсь, это поможет.Это хакерское злоупотребление блокировкой, но, возможно, оно сделает то, что вам нужно.