[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Custom extensions to Lua
- From: Rici Lake <lua@...>
- Date: Wed, 10 Aug 2005 14:57:58 -0500
On 10-Aug-05, at 2:06 PM, David Given wrote:
On Wednesday 10 August 2005 18:52, Rici Lake wrote:
C++, of course, provides the semantically odd reference type. Perhaps
that's what you were thinking of:
int& i = &ints->val;
int& j = i; /* ILLEGAL */
int& j = &i; /* Tell the compiler *not* to dereference i */
Actually, you're not quite right there --- lines 1 and 3 are invalid,
is valid. (I think that makes you exactly wrong!)
A reference can be initialised exactly once from a variable of the
int& i = j; /* i becomes an alias for j */
It can then be assigned to, but the assignment is actually performed
target of the reference:
i = k; /* j's value is modified to be that of k's value */
You can't change the target of a reference once it's been initialised.
very annoying it is, too.)
I stand corrected. This is why I hardly ever use C++... I should have
looked that all up before I blathered. My confusion comes from one of
the weirdnesses of references: the apparent similarity of the
definition and assignment syntax hide an implicit "enreference" and
"dereference" operator, respectively. (And these 'operators' are
inserted by the compiler.)
But the point stands: a reference is a very weird beast.
<useful example snipped>
This is phenomenally useful if you want to, say, add locks around
something, particularly when combined with generics. Take a look at
smart pointers some time. This allows you to do things like:
locked<int> value_l = &value; /* initialisation */
value_l = 1; /* lock, assign, unlock */
printf("%d\n", value_l); /* lock, copy, unlock, return copy */
Well, beauty is in the eye of the beholder :) Many people might prefer
synchronized int value;
although that doesn't give you the option of forgetting to use the
locked version :)
aList->setval(aList->getval() + 1);
rather than the arguably more readable:
You're not going to like me for this, but this is possible! It's a
pain in the
arse, though, and is usually not worth the effort. The key is to make
smart object which has operator++ overloaded.
I don't see how that allows 'aList' to maintain data coherency when its
'val' member is changed, unless the 'smart object' is so smart that it
knows about its container. That is, of course, possible but it's not
easy to see how to generalise it.
Suppose, for example, that aList is attempting to keep itself sorted.
Had the implicit mutate ("assignment") operation been directed at aList
in the first place, the implementation would be quite a bit clearer.
on defining a 'mutate box' primitive, which might be written ':=' or
'<-'; the semantics of 'foo <- val' would be fairly similar to the C
expression '*foo = val'.
*nods, although I'd write that last 'foo->assign(val)'*
No doubt. As I said, beauty is in the eye of the beholder :)
C++ gets away with this because it has two types of thing; scalars and
objects. (And references, but they're not relevant.) The = operator is
'assign' for scalars but 'mutate' for objects. You can overload
not scalars. So this:
foo = 0;
...is a fundamentally *different* operation to this:
foo = 0;
...despite syntactic similarities.
Sure. Furthermore, assignment and initialization are different, just to
be more confusing.
Whether an object and a "scalar" are different beasts is, I guess, a
philosophical question. Certainly you can override operations on
"objects" which cannot be overridden on "scalars" but one might think
of that as simply a restriction in the initial type environment. C++
does not, for example, guarantee that pointer assignment works like one
might naively think it does; the compiler itself is allowed to insert
code to, for example, maintain array boundaries in a pointer for
validation purposes, in which case, it is at least conceivable that you
might get a run-time exception from:
Object *foo = 0;
In Lua, everything is an object (or pretends to be one),
That depends on your definition of "object". I wouldn't have said that
myself (rather that in Lua every value has a definite type), but
terminology is a minefield. What is clear is that Lua, like Smalltalk
(at least), does not provide implicit boxes around values which can
receive messages. You can only talk to the value itself.
but like Smalltalk and Java it has no 'mutate' operator.
While one would be very useful, I do
find myself about dubious about whether it's possible to implement it
still be able to call the result Lua!
The simple answer is: "no". If you patch the Lua core, the best you can
say is that you've created a new language based on the Lua code. (At
least, I think the license lets you say that.)
The more interesting answer is that the patch to create an explicit
"box" type is not very big.
In fact, you could do it without patching the Lua core at all, using
only a preprocessor ( :) ), by representing a box as a table with one
distinguished key. The transformation would turn
a <- *a + 7
a.value = a.value + 7
or some variation on that theme. Mind you, you couldn't call the
preprocessor input Lua either, but you could certainly call it a
"language which can be compiled into Lua".