Vim script で関数の引数を不変にする

Vim script の関数の引数は基本的に読み取り専用なんですが、次のように思わぬところで辞書を書き換えてしまうようなケースがあります。

function! s:func(dict)
    " 呼び出し元の dict まで書き換えられてしまう
    call filter(a:dict, "len(v:val) < 4")
endfunction


let s:dict = {
\   0 : "zero" ,
\   1 : "one"  ,
\   2 : "two"  ,
\   3 : "three",
\   4 : "four" ,
\   5 : "five" ,
\}

call s:func(s:dict)
echo s:dict
" => {'1': 'one', '2': 'two'}


この場合、明示的に引数を不変にする事で、意図しないバグを防ぐことが出来ます。


[ソース]

function! s:func(dict)
    " a: をロックする
    lockvar! a:

    " これは a:dict がロックされているのでエラーになる
"     call filter(a:dict, "len(v:val) < 4")

    " こっちだとコピーしているので OK
    call filter(copy(a:dict), "len(v:val) < 4")
endfunction


let s:dict = {
\   0 : "zero" ,
\   1 : "one"  ,
\   2 : "two"  ,
\   3 : "three",
\   4 : "four" ,
\   5 : "five" ,
\}

call s:func(s:dict)
echo s:dict
" => {'0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five'}


便利便利。