Ruby の binding オブジェクトからローカル変数にアクセスする

Binding#local_variable_get でローカル変数にアクセスする事が出来ます。

def func a, b
    add = a + b

    # このメソッド内のコンテキストを返す
    binding
end

context = func 1, 2

# #local_variable_get でコンテキストの変数を取得する
p context.local_variable_get(:a)
# => 1
p context.local_variable_get(:b)
# => 2

# もしくは #eval を経由してもよい
p context.eval("add")
# => 3

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 で追加された関数 exepath()

Vim 8.0 で新しく exepath() という関数が追加されました。 これは『絶対パス相対パス、または $PATH の中に存在する場合は、そのフルパスを返す』という関数になります。

echo exepath("gvim")
" => /usr/local/bin/gvim

echo exepath("ruby")
" => /usr/bin/ruby

たまに Vim 自身がどの実行ファイルを参照しているのかを確認したい時があるので、地味に便利です。

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