lua-users home
lua-l archive

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


On Thu, Jun 27, 2013 at 8:28 PM, Rena <hyperhacker@gmail.com> wrote:
> On 2013-06-27 8:57 PM, "Tim Hill" <drtimhill@gmail.com> wrote:
>>
>> I'm going to get shot for suggesting this… (hides under bed)
>>
>> I've been writing a lot of Lua code recently, some of it quite generic in
>> nature. One thing I frequently come up against is the need to handle data
>> polymorphically in tables. And an effect of this is to hit against the
>> overloaded use of "nil" in Lua.
>>
>> It seems to me that "nil" is overloaded; it means both a noun: "no value"
>> and a verb: "delete this table entry". Now, most of the time, the delete is
>> hidden since reading a non-existent table entry returns nil. So having an
>> explicitly stored nil versus having no value stored at all is equivalent
>> (all this I love, btw … 100 points to Lua).
>>
>> But it all rather breaks down with arrays (sequences). I cannot have
>> sparse arrays, which in Lua terms means I cannot have "nil" in an array
>> element. So, when writing polymorphic code, how do I handle cases (which,
>> trust me, i DO have to handle, with "no value" in an array element? There
>> are, of course, a whole bunch of work-arounds: Use a sentinel value; use an
>> empty table (assuming empty tables aren't value data, and ignoring that each
>> one is unique); use a magic userdata (assuming I have access to C code to
>> make one); etc etc.
>>
>> But, let's face it; they ARE all workarounds. I think there IS a case to
>> be made for being able to store a value in a Lua array that is uniquely NOT
>> any other Lua value. Essentially, I think that value is "empty"; a valid Lua
>> value that is simply not the same as any other Lua value (including nil).
>>
>> Basically, empty would act like nil in most regards, except:
>> -- Storing empty in a table element actually stores the value, rather than
>> deletes it.
>> -- When used in a boolean context, the empty value evaluates to true
>> (unlike nil).
>> -- Has a type() of "empty"
>>
>> Other arguments in favor of this:
>> -- Judging by the mail list chatter, a lot of Lua beginners struggle with
>> the problem of nil in sequences.
>>
>> -- Better impedance matching to SQL NULL values; since empty can bridge to
>> a SQL NULL when a Lua array is used to hold a SQL row.
>>
>> Thoughts anyone?
>> --Tim
>>
>>

I think that you can have sparse arrays.

As I'm sure you're aware, you can modify __ipairs  and __len in any
way that you wish. So a metatable that marks the holes or provides the
length can be used in your version and then BAM! Sparse arrays. Heck,
you don't even need any storage. Just use make an __ipairs function
where the factory uses pairs to find the max int, picks the biggest
index and then poops out an iterator function that keeps going until
math.max is reached.


The implementation doesn't matter. I've posted emails just like yours
and like you, lately I've been doing more writing in Lua than writing
about it. The more that I use it, the more that I've come to
appreciate that it just isn't made to be the most convenient language
in the world. You end up doing quite a bit of typing, or you can use
its mechanisms to get what you want, ala how Penlight does it, which
probably has a sparse array module....

So, methods, not policies. Those work arounds that you've mentioned
are _how_ you do it, in Lua. That is the way. No need for yet another
"thing."

As an example, in my little library that I've built up for my project:
type looks at __type, error and assert use LuaLogger as well as
string.format, dogs hang out with cats, math has is_int, table is
overloaded with Penlight's tablex, coroutines can be made with tables
that have a __coroutine metatable field, and all manner of other
fluffery abounds. It's all good because I put it there and that's how
you're supposed to do it, if that's how you choose to roll... at least
that's what I've come to understand.

-Andrew