Getting Strict about Objects

13 views
Skip to first unread message

steve donovan

unread,
Feb 11, 2011, 1:22:38 AM2/11/11
to lua-table...@googlegroups.com
Hi all,

We got exhausted by talking about tables-as-lists and
tables-as-arrays, but there is another very important use: fields of
objects. (This comes out of a discussion Axel and I were having on
lua-l)

Of course, O["f"] == O.f remains the fundamental axiom on which it all
depends. But such a table can be constrained in useful ways.

Mostly importantly, it is _closed_. If a person did want to add
fields to an object, then they would be better with something
explicitly intended to be an associative array.

One approach I tried was this:

http://lua-users.org/wiki/StrictStructs

struct.Alice { -- declare a type Alice
x = ""; -- default values establish types
y = 2; -- and are useful for documentation
}
-- create an object of type Alice
a = Alice {x = "band", y = 20}

Since we have default values, Alice() can work as well. (If we had
field ordering, then Alice("band",20) could also work)

Now, the main feature of this scheme is that these are now runtime errors

print(a.z) --- Alice does not have a field 'z'
a.z = 2 -- ditto

The other feature is _identity_. Lua types are distinct (except for
some implicit conversions) but there aren't many of them - we of
course consider this part of its beauty. But 'creating types' is
useful since it's one more piece of information available to the
debugger or the crash handler.

Something like these these assertions becomes possible:

function f(a)
Alice.assert_typeof(a)
....
end

(Of course, with a proxy implementation you can even have 'a.x = 1'
raising a type error.)

Naturally, these 'strict structs' can support methods:

struct.Fred {
name = ""
function getName(self) return self.name end
}

There's a lot more diagnostic information in the message "Fred does
not have 'get_name'" than "calling a nil value".

Another small weapon in the fight against typos and misspelling.

steve d.

PS 'struct' is probably the wrong word (it's usually a namespace used
by Roberto's library anyway)

Axel Kittenberger

unread,
Feb 11, 2011, 4:20:21 AM2/11/11
to lua-table...@googlegroups.com
Hey, thank you for sharing thoughts, I'll add a few I had.

I quite agree with this, and have 3 strings of thoughts about this,
sorted from easy to do a sized dialect:

1) we had that "constraint" idea to make it easy to add metatables to
a table that constraints its contents in this or that way.

2) A useful language addon might be be able to set tables to readonly,
either completly readonly, or to "no keys added or removed". This
would additionally allow the hashtables to be optimized in size and
possibly even in hash function for readonly tables. This setting
readonly does not necessarily have to be at creation of the table, but
simply table.readonly(t)

3) This is the largest and furthest implicating idea I spend a few
hours upon I'll write now most about:

get rid of nil! (or "nil considered harmfull" :-)

In this nil-less-lua dialect accessing an element of any table that it
doent have will result in an error().

Why is getting rid of nil possibly a good idea? Nil has very some
strange (dirty) hybrid character, often its a value for "invalid",
"not there", "end of stream", but at the same time it is used as a
value meaning the name was "not there". I find this difficult to press
into words, but the discussions of functions not able to differentiate
if they are handed nil or the value wasn't there, and workaround with
select('#',...) should make this clearer.

Ok, now I suppose I didn't completly lose you in it being a good idea,
what does it all imply?

In some cases, there must be a way to test if a table (global) exists.
It should be concise. I'd think of the ? as operator
foo.bar?
is true if foo has bar, false if it doesnt. The ? operator always
applies to the last deference. So foo.bar.ooo? will error if foo has
not bar but be true or false depending if foo.bar has ooo or not.

So (foo.bar? and foo.bar) would be an idiom for if you not sure if foo
has bar and want it to be false if not or have its value if.

In lua function calls are not constrained to the number of parameters,
where the ones not specified are filled with nil. To get rid of nil
these must be filled with other default values.

function highlight(table, value=false)

value will be false if called with just highlight(foo). If you
strictly need to know a parameter not being able to given by the user
do this:

do
local empty = {}
function highlight(table, value=empty)
..
end
end

and no user can ever call it with 'empty', except just calling highlight(foo)

If you call the function with less parameters than it has default
values -> error()

Once nil is done for, there is no reason to keep implicit booleans.
Only false is false and only true is true.

Next "problem" is next() or other functions that return nil in case
there are no more items. In these cases the functions have to be
adapted to return two values, one if they are done (or how many items
are left), and one containing the value. It sounds like more impact,
but its cleaner, as again "nil" had this double meaning of nothing,
and sometimes people wished to add "nil" as meaning.

I think that was it, did I miss other places where mechanisms would
have to be changed to be compatible with nil-lessness?

BTW: I recently unsubscriped a little from lua-l :-(, it was too much
in my inbox, and only few messages were interesting (too many were
either bickering or clueless), maybe I'll subscribe again after a
pause, but lets see about it. I stay with you guys however! :-)

Reply all
Reply to author
Forward
0 new messages