|No, you make very good points, and of course these are very workable solutions … ALL the suggestions are that. My problem stems from good software design. The system I am designing is inherently very complex (has to be .. long story), and in any complex project you strive to manage that complexity, otherwise you are doomed. As we all know, one way to manage complexity is well defined module boundaries, and clearly delineated areas that do or do not have knowledge of other parts of the system (information hiding).|
One aspect of this is the need for a generic way to loft SQL results into Lua in an efficient (re: fast) manner where the underlying schema is NOT known to the transport code; it's sole job is one of packaging. In this model it's crazy to suggest (as some have stated) "you know your schema, so you know the structure of the results", because the lofting code does NOT know the schema .. nor SHOULD it, architecturally. In addition, this lofting has to happen on (OS) threads outside of Lua, and so CANNOT be linked (directly) to things like well-known magic tables. So I have to be able to (a) recognize NULLs, (b) loft them, (c) present them to Lua in a simple to consume manner.
When I design any interface or API, I strive to make it as "user friendly" as I can .. in fact one reason I like Lua is that the libraries seem to have that same philosophy .. tight, minimal, but powerful. Now, my experience of developers leads me to think that a naive developer, having just got to grips with Lua, would immediately think .."hmmm, database row … sounds like a Lua array", and I think he'd be right .. it's heterogenous, ordered (like a SQL row), and clean. And in a system where the schema (or perhaps even the SELECT statement being processed) is not known to the intermediate layers, a Lua array also carries type information for each element (via Lua type()) and the column count (via #). It's clean, easy, simple.
But it doesn't work, as Lua doesn't have enough "width" to its type system to handle the basic set of SQL types, and careful analysis says the problem here is NULL … the obvious mapping here is NULL -> nil, but then we hit on the issue where Lua arrays with "holes" (nil elements) are not arrays any more (any yes, I really, really, REALLY get why that is, trust me). So we need to invent a type that CAN tunnel in from an external non-Lua source and be efficiently surfaced. Hence my choice of a (void*)0 light userdata. Works perfectly.
But when I thought carefully, I felt that this had other applications in other areas of Lua. It allowed algorithms that had a need to mark an array item as "dealt with" or "processed" in a way that would not break the "array-ness" of the table that using nil does. Hence my suggestion. It wasn't a "how do I work around this?", it was a "if we think about this problem, isn't this something that might warrant further discussion?". Apparently, the answer is a resounding "shut up", which to be honest I think is a bit sad.
I've been working on complex software architectures for decades, and I've seen a lot of places where the lack of a "blessed" way to do something created a truly horrific mess. Perhaps i'm sensitized to this, but I still feel the Lua arrays are one of the more "odd" behaviors of the language. One moment its an array, the next its not. So when someone learning Lua says (a good question, btw), "ok, I get i'm not supposed to put nil in an array because they cannot be sparse, but what DO i put in?" .. and you say "it depends", I think you are punting a bit. Roberto suggested false, which sounds like he feels no-one ever needs to store booleans in an array .. a position I find odd.
On Jun 28, 2013, at 8:01 PM, Javier Guerra Giraldez <email@example.com> wrote:
as you can see, i don't agree with the idea that "this is just policy,