Ruby の binding オブジェクトと eval()
Ruby では現在のスコープのコンテキストを bindig オブジェクトとして扱う事が出来ます。
def func a, b add = a + b # このメソッド内のコンテキストを返す binding end p func 1, 2 # => #<Binding:0x00000000c0fe18>
[binding
オブジェクトと #eval()
]
bindig
の利用方法はいくつかありますが、#eval()
で使用するのがわかりやすいです。
def func a, b add = a + b # このメソッド内のコンテキストを返す binding end context = func 1, 2 # eval 内で func の変数などが参照できる p eval("add + a + b", context) # => 6
このように eval()
内で指定した binding
のコンテキストを参照する事が出来ます。
Vim 8.0 で追加された関数 funcref()
Vim 8.0 で新しく funcref()
という関数が追加されました。
これは function()
と同じように関数参照を取得する関数になりますが、『関数が上書きされても元の関数を呼び出す』という違いがあります。
function! Test() return "Test" endfunction let Function = function("Test") let Funcref = funcref("Test") echo Function() " => "Test" echo Funcref() " => "Test" " 関数を上書きする function! Test() return "new Test" endfunction " function() は上書きした関数を呼び出す echo Function() " => "new Test" " funcref() は元の関数を呼び出す echo Funcref() " => "Test"
上書きされる可能性がある関数の参照を取得したい場合は funcref()
を使用したほうが安全かもしれません。
Boost 1.62.0 がリリース
最近はあまり Boost も触っていないが Boost 1.62.0 がリリースされたらしい。
今回は新しく以下の2つのライブラリが追加された。
両方共、昔から提案はされていたもののなかなか組み込まれなかったので、今回追加されたのは感情深い。
Vim 8.0 で追加された機能 closure
Vim 8.0 では関数に closure 機能が追加されました。 これは、関数外のローカル変数をキャプチャするための機能です。
function! s:init() let value = 0 " closure キーワードを追加することで関数外のローカル変数をキャプチャできる function! s:count() closure let value += 1 return value endfunction endfunction " 関数を定義する call s:init() echo s:count() " => 1 echo s:count() " => 2 echo s:count() " => 3
Vim 8.0 で追加された機能 タイマーを一時停止する
前回書き忘れたので追記。
timer_pause()
を使用します。
" 一時停止 call timer_pause(timer_id, 1) " 再開 call timer_pause(timer_id, 0)
これで一時的にタイマーを停止したり、任意のタイミングで再開する事が出来ます。
Vim 8.0 で追加された機能 タイマー
Vim 8.0 ではついに Vim script にタイマー機能が追加されました!
この機能を使用することで処理をブロックしないで関数を呼び出すことが出来ます。
[基本的な使い方]
タイマーは timer_start()
関数を使用して任意の関数を n 時間後に呼び出す事が出来ます。
function! s:disp(timer) echo "callback" endfunction " 第一引数に時間、第二引数に呼び出す関数参照を渡す " 1000ミリ秒後に s:disp をブロックしないで呼び出す call timer_start(1000, function("s:disp"))
[タイマーを止める]
タイマーを止めたい場合、timer_start()
が返した ID と timer_stop()
を利用します。
" タイマーIDを受け取る function! s:disp(timer) echo "callback" endfunction let s:id = timer_start(1000, function("s:disp")) " ID のタイマーを止める call timer_stop(s:id)
コールバック関数が受け取る timer
は timer_start()
で生成された ID になります。
また、timer_stopall()
ですべてのタイマーを止める事が出来ます。
[回数を指定する]
timer_start()
の第三引数にリピートする回数を指定する事が出来ます。
let s:counter = { "value" : 0 } function! s:counter.count(...) echo self.value let self.value += 1 endfunction " 1000ms ごとに s:counter.count() を 3回呼び出す call timer_start(1000, s:counter.count, { "repeat" : 3 })
また、-1
をすることでタイマーを止めるまで呼ばれ続けます。
let s:counter = { "value" : 0 } function! s:counter.count(timer) echo self.value let self.value += 1 " 5回呼ばれたら止める if self.value >= 5 call timer_stop(a:timer) endif endfunction " 1000ms ごとに s:counter.count() を呼び出し続ける call timer_start(1000, s:counter.count, { "repeat" : -1 })
かなり便利。