Help us understand the problem. What is going on with this article?

Ruby 2.4でIntegerに一本化される整数

More than 3 years have passed since last update.

Ruby 2.4から、整数のクラスが付け変わることになりますが、特にCエクステンションを書いている場合は注意の必要があります。

Ruby 2.3までの世界

Rubyの世界にももちろん整数がありますが、(Ruby側から見て)今までは抽象クラスのIntegerの下に、絶対値の小さな整数についてはFixnum、それに収まらないものについてはBignumという具象クラスがある、というように分かれていました。このあたりについては、以前書いた記事が参考になるかと思います。

問題点

このような形にしていることで、いくつか問題がありました。

  • FixnumBignumは実装の詳細の違いで、Ruby側から違いが見える必然性はない
    • 同じ整数なのにFixnumBignumで挙動を違える、なんてことはむしろやるべきでない
  • 環境によってFixnumのサイズが違う(可搬性に乏しい)
  • RubyのISO規格上も、Integer以下は実装依存となっている

Ruby 2.4での変更点

そんなこともあって、Ruby 2.4からは両者がIntegerへ統合されることになりました。

Ruby側から見て

ふつうにプログラムを書いている中では、そもそもFixnumBignumを直接使う場面自体が少なかったでしょうし、そこまで大問題とはならないと思いますが、いくつか注意すべき点はあります。

既存のプログラムとの互換上、FixnumBignumという定数は存在し続けますが、どちらもIntegerのエイリアスとなります。それぞれをオープンクラスなどしていた場合も、直接Integerを変更するような形となります(きちんと対応する形に修正した方がいいでしょう)。

そして、foo.is_a?(Fixnum)のようにFixnumに収まるかチェックしていた場合、Ruby 2.4ではfoo.is_a?(Integer)とみなされて、整数であれば常にtrueとなります。(Cエクステンションが絡むような状況なら別として)Fixnumかどうかをチェックするという意図自体が根本的に問題なので、きちんと範囲チェックするように修正しましょう。

あと、これは実際に影響する場面もあるかもしれませんが、FixnumBignumという定数そのものをDSLの一部に使っていた場合、Integerと同じ値になってしまうのでうまく動かなくなります。使っているgemの説明に従って、適切に置き換えましょう。

C言語側から見て

Ruby上ではFixnumBignumの区別は廃止されましたが、C言語の世界では2種類の内部構造がそのまま存続する形となっています。ということで、「整数を扱う部分をすべて書き換える必要がある」なんてことにはなりません。

ただし、C言語上ではFixnumBignumを表すrb_cFixnumrb_cBignum廃止されています。これらの定数を使っていた場合、コンパイルエラーとなります。代替策としては、

  • 型チェックに使っていた場合→FIXNUM_P1RB_TYPE_Pなどで置き換えましょう。内部データ構造を示すためのT_BIGNUMは健在です。
  • メソッド定義などをしていた場合→Integerrb_cInteger)にセットする形に切り替えましょう。Fixnum用とBignum用の関数が別にある場合、内部で振り分けする必要が出てきます。

また、これらの振り分けを支援するための定数として、RUBY_INTEGER_UNIFICATIONが定義されています。#ifdef RUBY_INTEGER_UNIFICATIONで切り分けましょう。

自作gemのチェック

以前に作っていたjkr2255/bit_utils解説)について、コードをチェックしてみましたが、内部的にはFixnum用とBignum用のメソッドがあって、

  • Fixnum用…Bignumを投げるとエラーになる
  • Bignum用…Fixnumでも動くけど、少し余分な処理が入る

というようになっていました。そして、Fixnumをオープンして使うとき以外はBignum用をそのまま使うようになっていて、オープンクラス時もFixnumBignumの順で行っていたので、そのままですべてがうまくいくような流れになっていました。Ruby 2.4.0-preview2でも正常に動作しました。

とはいえ、FixnumBignumを両方オープンしているのも行儀が悪いので、書き換えを行う予定です。

参考資料

RubyKaigiで発表されたスライドのPDF


  1. 1ビットを見るだけなので、きわめて高速です。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした