CML の CACHE_MISS と CACHE_HIT
>たぶん誰ひとりとして興味ないと思うけど、ついつい lua のソースなどを見てしまった。で、結論から言うと、型の誤りによるものだった。 CACHE_MISS や CACHE_HIT は、 lua_pushboolean を使って値を定義しているから真理値の値をもつ(ところで、どちらでも良いとはいえ CACHE_MISS が true なのはどうかと思う)。一方、 cml ファイルの評価結果は lua_tonumber で取得しているようだ。
>
>lua_tonumber のコードを見ると、
>
>LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
TObject n;
const TObject *o = luaA_indexAcceptable(L, idx);
if (o != NULL && tonumber(o, &n))
return nvalue(o);
else
return 0;
} > >細かいところはあまりよくわからないが、指定したオブジェクトを o として取得してから、 null かどうかの判定などをしているということだと思われる。 んで、 tonumber では、 o の型が LUA_TNUMBER かどうかのチェックをしている(それだけではないが今回意味があるのはそれだけ)。ということで今回の場合、 CACHE_HIT にせよ CACHE_MISS にせよ真理値型なので、この判定でミスる。したがって 0 が返される。 > >ところで昨日のエントリを見てほしいわけだが、 cml では 0 が成功、 1 がキャッシュミスを意味していたわけだ(たぶん CACHE_* は後で追加されたのだと思う)。tonumber が失敗すると 0 を返すという仕様と組み合わせると、 CACHE_* を使っているかぎりキャッシュミスは発生しないということになる。どうも上手く行かない原因はここにあったわけだ。なるほどなあ。 > >対処は簡単で、 lua_pushboolean になっているのを lua_pushnumber にしてやればよい。もちろん返戻値を lua_toboolean にしても問題ないけど、後方互換性が保てなくなるという問題がある。 boolean でないものを toboolean しようとすると真が返るので、従来的な 0 か 1 を返すやり方では絶対にキャッシュが成功しなくなります。 >
TObject n;
const TObject *o = luaA_indexAcceptable(L, idx);
if (o != NULL && tonumber(o, &n))
return nvalue(o);
else
return 0;
} > >細かいところはあまりよくわからないが、指定したオブジェクトを o として取得してから、 null かどうかの判定などをしているということだと思われる。 んで、 tonumber では、 o の型が LUA_TNUMBER かどうかのチェックをしている(それだけではないが今回意味があるのはそれだけ)。ということで今回の場合、 CACHE_HIT にせよ CACHE_MISS にせよ真理値型なので、この判定でミスる。したがって 0 が返される。 > >ところで昨日のエントリを見てほしいわけだが、 cml では 0 が成功、 1 がキャッシュミスを意味していたわけだ(たぶん CACHE_* は後で追加されたのだと思う)。tonumber が失敗すると 0 を返すという仕様と組み合わせると、 CACHE_* を使っているかぎりキャッシュミスは発生しないということになる。どうも上手く行かない原因はここにあったわけだ。なるほどなあ。 > >対処は簡単で、 lua_pushboolean になっているのを lua_pushnumber にしてやればよい。もちろん返戻値を lua_toboolean にしても問題ないけど、後方互換性が保てなくなるという問題がある。 boolean でないものを toboolean しようとすると真が返るので、従来的な 0 か 1 を返すやり方では絶対にキャッシュが成功しなくなります。 >