🎩

Gauche: eq?, eqv?, equal? の実装コードを探す

2020/10/23に公開

Scheme の等価性の判定については、eq?, eqv?, equal? の 3 つの述語があります。
それぞれがどのように比較を行うかについては、リファレンスマニュアルに書かれてあります。

ここでは Gauche の eq?, eqv?, equal? がどのようなコードで実装されているか見ていきましょう。

eq?, eqv?, equal? の実装コードを探そう

REPL から describe コマンドを実行し、eq? についての情報を出力してみます。

gosh> ,d eq?
#<subr (eq? obj1 obj2)> is an instance of class <procedure>
Defined at "libbool.scm":47
slots:
  required  : 2
  optional  : #f
  optcount  : 0
  locked    : #f
  currying  : #f
  constant  : #t
  info      : (eq? obj1 obj2)
  setter    : #f

eq? は、libbool.scm の 47 行目で定義されていることが分かりました。
さっそくソースを覗いてみると、次の定義が見つかります。

libbool.scm
(define-cproc eq? (obj1 obj2)  ::<boolean> :fast-flonum :constant
  (inliner EQ) SCM_EQ)

ふーむ。確かに eq? の定義のようではありますが、普段書いている Scheme コードとは雰囲気が違いますね。どうやら Scheme の世界から Gauche の実装言語(C 言語)への入り口に立っているようです。

おそらく、C 言語で書かれた eq? の実装がきっとどこかにあるはずです。
すぐ隣に eqv?, equal? も定義されているので、それも見ておきましょう。

libbool.scm
(define-cproc eqv? (obj1 obj2) ::<boolean> :fast-flonum :constant
  (inliner EQV) Scm_EqvP)

(define-cproc equal? (obj1 obj2) ::<boolean> :fast-flonum Scm_EqualP)

いかにも定義らしい SCM_EQ, Scm_EqvP, Scm_EqualP で grep してみましょう。
すると、gauche.h に見つかります。

gauche.h
#define SCM_EQ(x, y)         ((x) == (y))

SCM_EXTERN int Scm_EqP(ScmObj x, ScmObj y);
SCM_EXTERN int Scm_EqvP(ScmObj x, ScmObj y);
SCM_EXTERN int Scm_EqualP(ScmObj x, ScmObj y);

さらに Scm_EqP で grep すると boolean.h に実装が見つかります。ついに実装までたどり着くことが出来ました。

boolean.h
int Scm_EqP(ScmObj x, ScmObj y)
{
    return SCM_EQ(x, y);
}

int Scm_EqvP(ScmObj x, ScmObj y)
{
    /* 略 */
}

int Scm_EqualP(ScmObj x, ScmObj y)
{
    /* 略 */
}

eq?, eqv?, equal? の実体は、それぞれ C 言語の Scm_EqP, Scm_EqvP, Scm_EqualP の関数ということが分かりました。

Discussion