天泣記

2015-09-27 (Sun)

#1 string literal をファイル単位で frozen にできるようになった

[Feature #8976] [ruby-core:57574] file-scope freeze_string directive がついに実装された。

これは、文字列リテラルの解釈を変える機能を提供する。通常、以下のように、文字列リテラルが返す文字列オブジェクトは frozen ではない。

% ./ruby -e 'p "foo".frozen?'
false

しかし、これが frozen-string-literal: true という pragma によって、frozen となる。なお、false なら frozen とはならず、現状どおりとなる。(ここでは -e オプションの引数に書いてあるが、普通はファイルの先頭に書くことになる)

% ./ruby -e '# -*- frozen-string-literal: true -*-
p "foo".frozen?'
true
% ./ruby -e '# -*- frozen-string-literal: false -*-
p "foo".frozen?'
false

現在は文字列リテラルを評価する度に文字列オブジェクトが生成されるが、frozen になると毎回同じ文字列オブジェクトを返しても問題なくなり、実際、同じ文字列オブジェクトを返すようになる。これは GC の発生頻度を減らすことが期待される。

pragma はファイル毎の指示だが、--enable-frozen-string-literal, --disable-frozen-string-literal というコマンドラインオプションによって、すべてのファイルに対して影響を与えることもできる。

% ./ruby --enable-frozen-string-literal -e 'p "foo".frozen?'
true
% ./ruby --disable-frozen-string-literal -e 'p "foo".frozen?'
false

なお、コマンドラインオプションが与えられて、かつ pragma も存在する場合は、pragma が優先である。

% ./ruby --enable-frozen-string-literal -e '# -*- frozen-string-literal: true -*-
p "foo".frozen?'
true
% ./ruby --disable-frozen-string-literal -e '# -*- frozen-string-literal: true -*-
p "foo".frozen?'
true
% ./ruby --enable-frozen-string-literal -e '# -*- frozen-string-literal: false -*-
p "foo".frozen?'
false
% ./ruby --disable-frozen-string-literal -e '# -*- frozen-string-literal: false -*-
p "foo".frozen?'
false

従って、この機能を使うかどうかはファイル毎に判断していき、使うことにするなら pragma を書く、というように進めていけばよい。乱暴には、--enable-frozen-string-literal をつけてテストして、うまく動くようなら pragma をつける、という感じだろうか。

% ./ruby -v
ruby 2.3.0dev (2015-09-27 trunk 51954) [x86_64-linux]

[latest]


田中哲