読者です 読者をやめる 読者になる 読者になる

odd?

mosh

奇数かどうかを調べる手続き。奇数は2で割るとあまりがでる整数
Gaucheでちょこっと試してみる。

gosh> (odd? 3.0)
#t
gosh> (odd? 3)
#t
gosh> (odd? 3.1)
*** ERROR: integer required, but got 3.1
Stack Trace:
_______________________________________
gosh> (odd? 3+1i)
*** ERROR: integer required, but got 3.0+1.0i
Stack Trace:
_______________________________________

コードだと

int Scm_OddP(ScmObj obj) 
{
    if (SCM_INTP(obj)) {
        return (SCM_INT_VALUE(obj)&1);
    }    
    if (SCM_BIGNUMP(obj)) {
        return (SCM_BIGNUM(obj)->values[0] & 1);
    }    
    if (SCM_FLONUMP(obj) && Scm_IntegerP(obj)) {
        return (fmod(SCM_FLONUM_VALUE(obj), 2.0) != 0.0);
    }    
    Scm_Error("integer required, but got %S", obj);
    return FALSE;       /* dummy */
    
}

で動きは分かる。実数でも整数とみなせるものは計算しているのは仕様外ではあるのかな。
とりあえずmosh内部の型情報を見る辺りは抑えないと話にならないな。


型が何であるかを見る方法は見当がついた。Scm_IntegerPに相当するのがまだないので、そっち相当のを先にやらないといけない。あと、fixnumようのfxodd?と実数用のflodd?というのがあるようなので
fixodd?とflodd?を実装して、

Object scheme::oddPEx(int argc, const Object* argv)
{
    DeclareProcedureName("odd?");
    checkArgumentLength(1);
    const Object obj = argv[0];
    if (obj.isFixnum()) {
        fixoddPEx(argc, argv);
    } else if (obj.isFlonum()) {
        floddPEx(argc, argv);
    } else if (obj.isBignum() || obj.isRatnum()) {
        // hogehoge
    }
    // error
}

のような感じにするんだろうか。