既にお気付きだと思いますが、Vim では List または Dictionary 変数を辞書のキーとして使用することはできません。つまり、たとえば、次のように「チェック済み」の辞書を作成することはできません。
" Unless k is a String, this won't work.
:let checked[k] = 1
また、リストまたは辞書から一意の文字列を生成する簡単な方法がないため、これも信頼できません。
:let checked[ string(k) ] = 1
より良いアプローチは、ハッシュテーブルを構築しようとする代わりに、データ構造自体をマークすることです。データ構造を一時的に読み取り専用にすることを気にしない場合、その方法の 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
お役に立てれば。これはロック機能のハックな悪用ですが、おそらく必要なことは実行してくれるでしょう。