• Subject: Re: LuaJIT 64 bit integers (was: the purpose of lightuserdata)
• From: Josh Haberman <jhaberman@...>
• Date: Thu, 13 Jan 2011 17:05:47 +0000 (UTC)

```Mike Pall <mikelu-1101 <at> mike.de> writes:
> Josh Haberman wrote:
> > Speaking as someone who has previously asked for a __hasheq
> > metamethod [0], I got over it, and I would hate for this slippery
> > slope worry to lead to semantics where:
> >-
> >   1 == 1LL
> >   t[1] != t[1LL]
> >-
> > That sounds extremely counter-intuitive.
>-
> Then you'll be even more surprised that t[1LL] != t[1LL], because
> neither cdata not cdata literals are interned.

Yes, I shudder to think of explaining that to users.  I was initially
very excited to hear your announcement of 64-bit integer support since
it's been a stumbling block for adoption of Lua inside Google where we
have lots of 64-bit integers floating around, but these semantics seem
so counter-intuitive that I'd hesitate to advocate people use them.
By the time I'm explaining that regular numbers and 64-bit numbers
have different table semantics because one is built-in and one is
cdata I think I will have lost my audience.  People who are new and/or
infrequent users of a language have only so much brain space to fill
up with unexpected quirks.

> Then t[1LL] should map to t[1], so both would need to end up in
> the array part of a table. Ok, so a table traversal would return
> the key as 1 and not 1LL, which may lead to even more confusion.

It shouldn't be confusing if 1LL and 1 behave identically for key
operations like comparison and table indexing.

> And then t[10000000000000000LL] needs to map to t[1e16].

Makes sense.

> But t[9999999999999999LL] shouldn't map to t[1e16], even though
> tonumber(9999999999999999LL) == 1e16.

I don't see the problem with this.

9999999999999999LL == 1e16 => false
t[9999999999999999LL] == t[1e16] => false

tonumber(9999999999999999LL) == 1e16 => true
t[tonumber(9999999999999999LL)] == t[1e16] => true

It seems perfectly consistent to me.  9999999999999999LL and
tonumber(9999999999999999LL) are different and do not compare equal,
because tonumber() is a lossy conversion.

> And the final catch is that
> t[-1LL] and t[-1ULL] better both map to t[-1], even though
> tonumber(-1LL) == -1 and tonumber(-1ULL) == ~1.844674407371e+19.

Why would t[-1ULL] map to t[-1]?  I certainly wouldn't expect
-1ULL == -1 or -1ULL == -1LL.  I think it's still consistent:

-1ULL == -1 => false
t[-1ULL] == t[-1] => false

-1ULL == -1LL => false
t[-1ULL] == t[-1LL] => false

-1ULL == 1.844674407371e19 => true (or whatever the exact constant is)
t[-1ULL] == t[1.844674407371e19] => true

> Ouch! That's a can of worms I *really* don't want to open. This is
> not ever going to work in a sensible way.

I think it's really consistent and logical if you just follow the same
semantics as == (with the exception of the __eq metamethod, as you
noted).  If you can make == work sensibly between numbers and int64_t,
why not table indexing?

Josh

```