SPECIAL_CONST_P

SPECIAL_CONST_P の実装を見てみる。

https://github.com/ruby/ruby/blob/ruby_2_6/include/ruby/ruby.h#L1297

#define RB_SPECIAL_CONST_P(x) (RB_IMMEDIATE_P(x) || !RB_TEST(x))
#define SPECIAL_CONST_P(x) RB_SPECIAL_CONST_P(x)

どうやら、x について、

  • RB_IMMEDIATE_P(x) である、もしくは
  • RB_TEST(x) ではない

ということらしい。ちなみに、RB_ prefix アリなしがあるのは、昔は RB_ 無ししかなかったけど、やっぱりあったほうがいいだろうって後から追加されたため(たしか)。MRI にはこういうのが結構ある。今は、RB_ 付きを使っておくのが良いと思う。

もうひとつちなみに、_P (もしくは、関数の場合は _p) suffix は、predicate、述語の意味で、Ruby だと special_const? みたいなメソッドの意味。C だと ? を識別子に使えないからね。

それぞれの定義も引用する。

https://github.com/ruby/ruby/blob/ruby_2_6/include/ruby/ruby.h#L400

#define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK)
#define IMMEDIATE_P(x) RB_IMMEDIATE_P(x)

https://github.com/ruby/ruby/blob/ruby_2_6/include/ruby/ruby.h#L478

#define RB_TEST(v) !(((VALUE)(v) & (VALUE)~RUBY_Qnil) == 0)

ビット計算が入ってきていて、微妙によくわからなくなっている。

実装はともかく、それらが何をしているかというと、

  • RB_IMMEDIATE_P(x) は、x が Fixnum、static Symbol、Flonum、true の時に真
  • RB_TEST(x) は、xnil、false の時に真

ということで、前項で述べた special const なオブジェクトに対応する。