【一人 bugs.ruby Advent Calendar 2020】[Feature #12901] Anonymous functions without scope lookup overhead【13日目】

一人 bugs.ruby Advent Calendar 2020 13日目の記事になります。

[Feature #12901] Anonymous functions without scope lookup overhead

Proc などを定義する際に『外部のスコープを参照しないこと』を明示化することでオーバーヘッドをなくしパフォーマンスを向上させるチケットです。

# scope: false をキーワード引数で渡すことで『キャプチャしないこと』を明示化
Proc.new(scope: false) {|var| puts var }

# これは以下のようにメソッドを定義したときと同じ意味
def anon(var)
  puts var
end


# 動作例
var = "hello"
Proc.new(scope: false) { puts var }.call
# => NameError: undefined local variable or method `var' for main:Object

内容がかなり難しいので適当に拾うと * bindingself が絡んでくると最適化するのがむずかしい * self をキャプチャしない場合は puts some_expression が動かないよね

みたいな議論がされてるぽい?です。
他には以下のように def->(a) = という構文で UnboundMethod みたいなもの生成するのはどうか、みたいな提案もされていました。

# plus が UnboundMethod ぽいオブジェクトになる
plus = def->(a) = self + a

# plus は第一引数を self として受け取り、それ以降は def で定義した仮引数で受け取る
plus.bind_call(1, 2) #=> 3
plus_1 = plus.bind(1)
plus_1.call(11) #=> 12

なんかこのあたりの変数スコープの話を見てると C++ラムダ式を思い出しますね。
C++ラムダ式Ruby とは違い明示的にキャプチャする変数を指定するような形になっています。

auto a = 1;
auto b = 2;
// [] に参照する変数を指定する
auto plus = [a](auto x) {
    // このスコープ内では a しか参照できない
    return a + x;
};

Ruby でもこんな感じで明示化するといいんですかね?めんどくさいかなぁ。