Misoca開発チームのeitoballです。RubyKaigi2015 が、もうすぐ開催ですね。ワクワクしています。
今日は、前回 に引き続き、Ruby 2.3 の新しく追加される予定の機能を試していきたいと思います。今回は、組み込みライブラリの非互換な変更と標準ライブラリの変更を見ていきます。
組み込みライブラリの互換性のない変更
Array
Array#select!
Array#keep_if
Array#reject!
Array#delete_if
ブロックを呼び出す毎に呼び出し元の Array
オブジェクトを変更しないようになります。[Feature #10714]
配列の長さに応じて指数関数的非線形にこれらのメソッドの処理時間が長くなってしまうのを防ぐためにこの変更が適用されたようです。
以下のようなコードで試してみました。2.3 と 2.2 の実行結果を比べてみると 2.2 では、途中で配列の長さが変わっています。2.3 でも、配列の内容は途中で変わっていますが、このようなメソッドを使うときは、配列の別の部分を参照する必要がないはずなので、問題ないと思います。
a = [1, 2, 3, 4, 5, 6] a.reject! do |e| p a e % 2 == 1 end p a
ruby 2.3.0preview1 (2015-11-11 trunk 52539) [x86_64-darwin14] [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6] [2, 2, 3, 4, 5, 6] [2, 2, 3, 4, 5, 6] [2, 4, 3, 4, 5, 6] [2, 4, 3, 4, 5, 6] [2, 4, 6]
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin14] [1, 2, 3, 4, 5, 6] [2, 3, 4, 5, 6] [2, 3, 4, 5, 6] [2, 4, 5, 6] [2, 4, 5, 6] [2, 4, 6] [2, 4, 6]
Array#pack
使用できるテンプレート文字に j
と J
が追加されます。それぞれプラットフォーム上のポインタと同じサイズの整数と符号付き整数です。 [Feature #11215]
Enumerable
Enumerable#chunk
、Enumerable#slice_before
引数として、initial_state
を受け取らないようになります。状態を管理するには、ローカル変数を使用して下さい。 [Feature #10958]
2.2 で、すでに警告が出ていますので、順当な廃止だと思います。
$ ruby -ve '[3, 2, 4, 5].chunk("state") { |elt, state| elt % 2 == 0 }' ruby 2.2.3p173 (2015-08-18 revision 51636) [...] -e:1: warning: initial_state given for chunk. (Use local variables.)
File::Stat
File#Stat#ino
Windows プラットフォーム上では、常に 0
を返していましたが、Windows API での BY_HANDLE_FILE_INFORMATION
構造体の nFileSizeHigh
と nFileSizeLow
を合わせたもの(nFileSizeHigh << 32 | nFileSizeLow
)を返します。
IO
IO#close
IO
オブジェクトが既にクローズしている IO
オブジェクトに対して、 #close
を読んでも、 IOError
は、発生しなくなります。 [Feature #10718]
IO#each_codepoint
入力の終端(EOF)に達する前に変換できないキャラクタに遭遇すると例外(ArgumentError
)が発生するようになります。 [Bug #11444]
Module
Module#define_method
メソッド定義、Proc
、もしくは、Method
のインスタンス、ブロックが必要になります。ブロックがない場合は、ArgumentError
が発生するようになります。 [Bug #11283]
class Foo define_method(:with_body) { p self } # => ok define_method(:with_proc, Proc.new { p self }) # => ok define_method(:with_method, self.new.method(:to_s)) # => ok class << self def define_method_with_block(&block) define_method(:with_block, &block) end end define_method_with_block { p self } # => ok define_method(:no_body) # => ArgumentError: `define_method': tried to create Proc object without a block
Object
Object.define_singleton_method
Module#define_method
と同様です。
String
String#unpack
Array#pack
と同様です。
標準ライブラリの変更(主なもののみ)
Net::FTP
Net::FTP#mlst
、Net::FTP#mlsd
の追加
RFC 3659 で定義されている MLST と MLSD コマンドを発行するメソッドが追加されます。
ObjectSpace
(objspace
)
ObjectSpace.count_symbols
の追加
シンボルを種類ごとにカウントした結果を Hash
として返すメソッドが追加されます。ソースコード(ext/objspace/objspace.c
)には、"This method is only for MRI developers interested in performance and memory usage of Ruby programs." とコメントがあり、CRuby 開発者向けのようです。
irb> require 'objspace' irb> ObjectSpace.count_symbols => {:mortal_dynamic_symbol=>0, :immortal_dynamic_symbol=>1, :immortal_static_symbol=>3587, :immortal_symbol=>3588}
- mortal_dynamic_symbol: ガーベジコレクタ(GC)により回収される予定の(動的に作成された)シンボルの数
- immortal_dynamic_symbol: GC で回収されないようにマークされた動的に作成されたシンボルの数
- immortal_static_symbol: GC で回収されない(静的に作成された)シンボルの数
- immortal_symbol: GC で回収されない全ての種類のシンボルの数(
immortal_dynamic_symbol
とimmortal_static_symbol
の合計)
ObjectSpace.count_imemo_objects
の追加
(これはよくわかりません。)ruby内部(VM)で使用される特別なオブジェクトを種類ごとにカウントした結果を Hash
として返すメソッドが追加されます。このメソッドにも ObjectSpace#count_symbols
と同じコメントがあり、CRuby 開発者向けのようです。
irb> require 'objspace' irb> ObjectSpace.count_imemo_objects => {:imemo_iseq=>1162, :imemo_ment=>3604, :imemo_cref=>279, :imemo_svar=>103, :imemo_throw_data=>2, :imemo_ifunc=>6, :imemo_memo=>6}
ObjectSpace.internal_class_of
の追加
オブジェクトの ruby 内部でのクラスを返すメソッドが追加されます。ソースコード(ext/objspace/objspace.c
)には、"Note that you should not use this method in your application." とコメントされています。
irb> require 'objspace' irb> s1, s2 = '', '' irb> [s1, s2].map { |s| ObjectSpace.internal_class_of(s) } [String, String] irb> s1.singleton_class # => 特異クラスを作成 #<Class:#<String:0x007fe123836268>> irb> [s1, s2].map { |s| ObjectSpace.internal_class_of(s) } => [#<Class:#<String:0x007fe123836268>>, String]
ObjectSpace.internal_super_of
の追加
クラス、もしくは、モジュールの ruby 内部での親クラスを返すメソッドが追加されます。ソースコード(ext/objspace/objspace.c
)には、"Note that you should not use this method in your application." とコメントされています。
irb> require 'objspace' irb> String.ancestors => [String, Comparable, Object, Kernel, BasicObject] irb> s1 = ObjectSpace.internal_super_of(String) => #<InternalObject:0x007f8b8c8d4108 T_ICLASS> # Comparable のための内部クラス irb> s2 = ObjectSpace.internal_super_of(s1) => Object irb> s3 = ObjectSpace.internal_super_of(s2) => #<InternalObject:0x007f8b8c8dd618 T_ICLASS> # Kernel のための内部クラス irb> s4 = ObjectSpace.internal_super_of(s3) => BasicObject irb> s5 = ObjectSpace.internal_super_of(s4) => nil
OpenSSL
OpenSSL::SSL::SSLSocket#accept_nonblock
と OpenSSL::SSL::SSLSocket#connect_nonblock
での、exception: false
のサポート
ARGF.read_nonblock
のように exception: false
を指定すると OpenSSL::SSL::SSLSocket#accept_nonblock
を呼び出した際、IO::WaitReadable
や IO::WaitWritable
が発生する代わりに :wait_readable
や :wait_writable
が返されるようになります。
Pathname
Pathname#descend
、Pathname#ascend
での、ブロックなしでの呼び出しのサポート
Pathname#descend
と Pathname#ascend
で、ブロックなしで呼び出すと Enumerator
オブジェクトが返すようになります。 [Feature #11052]
e = Pathname.new('/path/to/some/file.rb').descend e.each do |v| p v end
Socket
Socket#connect_nonblock
、Socket#accept_nonblock
、他5メソッド
ARGF.read_nonblock
のように exception: false
を指定すると これらのメソッドを呼び出した際、IO::WaitReadable
や IO::WaitWritable
が発生する代わりに :wait_readable
や :wait_writable
が返されるようになります。
適用されるメソッドは以下になります。
Socket#connect_nonblock
Socket#accept_nonblock
TCPServer#accept_nonblock
UNIXServer#accept_nonblock
BasicSocket#recv_nonblock
BasicSocket#recvmsg_nonblock
BasicSocket#sendmsg_nonblock
BasicSocket#recv
、BasicSocket#recv_nonblock
で、入力を格納するための String
オブジェクトの受け入れのサポート
IO#read
や IO#read_nonblock
のように入力を受け入れるための String
オブジェクトを受け付けるようになります。「to reduce GC overhead
」との事です。
require 'socket' buf = '' UNIXSocket.pair do |s1, s2| s1.puts "Hello World" s2.recv(4, nil, buf) } p buf #=> "Hell"
IO
(io/wait
)
IO#wait_readable
の変更
IO#wait_readable
は、読む込むことができるバイトがあるかどうかチェックしないようになります。
Object
(timeout
)
Object#timeout
このメソッドが呼ばれるとこのメソッドは将来廃止され、 Timeout.timeout
を使うように警告を発するようになります。
修正履歴
- [2015-12-11 07:20] "
Array#select!
Array#keep_if
..." で、「配列の長さに応じて指数関数的に」を「配列の長さに応じて指数関数的非線形に」に修正しました。(コメント#1)