lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



On 27-Aug-05, at 10:44 PM, Chris Marrin wrote:

If I found this acceptable:

    local a = SFBoolean(true)
    if a == SFTrue then...

then all would be well. But I don't. Even these two:

    if a == true then...
    if a:valueOf() then...

which both work after I made my "fix" to __eq, is not acceptable to me. It has to be:

    if a then...

so I will have to make the change to the VM.

Now you're just being stubborn :)

If you use Lua 5.1, you can attach a metatable to the boolean type. It only has two instances, true and false. So SFBoolean can be the identity operator. The only limitation that this brings is that you can only have a single instance of the false object. I don't see this as problematic.

All non-false objects (except, of course, nil) will satisfy

  if a then ...

So there is absolutely no problem with having multiple true objects.

Now, if you wanted to implement a non-deterministic language, this wouldn't work:

local a = SFBoolean("maybe")

if a then -- maybe it jumps, maybe it doesn't :)
...
end

There are applications for this sort of thing but I have a hunch that yours isn't one of them.

If I'm missing something obvious, feel free to continue this thread...

By the way, I checked the 5.1work6 code. It still insists that objects have the same (lua) type in order to be compared, so it won't do what you want. It would be easy-ish to change the check to "same metamethod" with a little jiggling.

Current lessthan:

int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
  int res;
  if (ttype(l) != ttype(r))
    return luaG_ordererror(L, l, r);
  else if (ttisnumber(l))
    return luai_numlt(nvalue(l), nvalue(r));
  else if (ttisstring(l))
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
    return res;
  return luaG_ordererror(L, l, r);
}

change:

int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
  int res;
  if (ttype(l) == ttype(r)) {
    if (ttisnumber(l))
      return luai_numlt(nvalue(l), nvalue(r));
    else if (ttisstring(l))
      return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
  }
  if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
    return res;
  return luaG_ordererror(L, l, r);
}

Current lessequal:

static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
  int res;
  if (ttype(l) != ttype(r))
    return luaG_ordererror(L, l, r);
  else if (ttisnumber(l))
    return luai_numle(nvalue(l), nvalue(r));
  else if (ttisstring(l))
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
    return res;
else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
    return !res;
  return luaG_ordererror(L, l, r);
}

change:

static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
  int res;
  if (ttype(l) == ttype(r)) {
    if (ttisnumber(l))
      return luai_numle(nvalue(l), nvalue(r));
    else if (ttisstring(l))
      return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
  }
  if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
    return res;
else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
    return !res;
  return luaG_ordererror(L, l, r);
}

In the case of ==, the following ought to work:

in lvm.h:

#define equalobj(L,o1,o2) \
        (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))

change to

#define equalobj(L,o1,o2) \
        (ttype(o1) == ttype(o2) \
            ? luaV_equalval(L, o1, o2))
            : call_orderTM(L, o1, o2) > 0

(However, you'd have to change call_orderTM to luaV_callOrderTM and add it to the lvm.h header, I believe.)

I haven't tried any of that, and I'm don't think I like it. I would certainly want to have an non-overridable object equality primitive in the language ('is' '===' or however you spell it).