XMLRPC 0.0 for Lua

classic Classic list List threaded Threaded
60 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: unified methods

John Belmonte-2
> The same thing applies here to unified methods. Sure, its just a
> face lift of the current tag method system, but as you stated
> yourself, the current tag method system is spotty and hard to
> follow. Unified methods gives the tag method system a more
> consistant and easy to follow interface. If that is the type of
> "illusion" you are speaking of, I see no problem with them.

When people misunderstand which side I'm on that means my illusion of being
unbiased is working  ; )

-John



Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Paul Chakravarti
In reply to this post by Edgar Toernig
Edgar Toernig writes:

>> (http://lua-users.org/wiki/BooleanTypeProposal) I had a slight question/concern with the following -
 -- Relational operators return false for false and a value other than
 -- false/nil for true

In fact, they always return the number 1 for true.  Maybe it's better
to say that explicitely (and define true to be 1). That way (a==b) == (c==d) and alike becomes valid.

I would prefer that this explicitly evaluated to a distinct 'true'
type - if there is no explicit 'true' value it is impossible to
correctly serialise the value for an API which expects a destinct
boolean value (in this case specifically XMLRPC but generally true) by
checking the type.
eg. { aaa = true|false } will be serialised as a boolean if false
(as this is a distinct type) but as an integer if true & true is
represented as "1".
This could be fixed by explicity casting to a user type but this is
somewhat ugly.

And then define that if/while/not/... only accept 'false' and 'true'?
I thought about it myself but IMHO it complicates things more than
it would help.

I dont think that this is necessary - all non nil/false values can
still be treated as true - this is just a specialisation of the
inplementation to include a 'true' class which is returned by
relational operators (and can be explicitly assigned) - I dont think
that this changes the semantics at all just makes it easier to detect
boolean values for code that requires this (relational opeartors still
return a non-nil value as per the current implementation - this non-nil
value just happens to have a type of 'true') Regards, PaulC

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

John Belmonte-2
Paul Chakravarti wrote:
> I would prefer that this explicitly evaluated to a
> distinct 'true' type - if there is no explicit 'true' value
> it is impossible to correctly serialise the value for
> an API which expects a destinct boolean value (in
> this case specifically XMLRPC but generally true) by
> checking the type.

Scheme is a pretty serious as far as languages go and it manages to get by
with just a false type.

Maybe expecting tables (or the language) to support full marshaling
out-of-the-box is too much.  There are still cases where you want some type
associated with each field but want to allow for nil values.  For example
field "email_address" is a string but it happens to be nil right now meaning
it's invalid or undefined.  When you need that you're back to Rici Lake's
table of tables technique.

-John



Reply | Threaded
Open this post in threaded view
|

Re: unified methods

Edgar Toernig
In reply to this post by John Belmonte-2
John Belmonte wrote:
> 
> Actually unified methods doesn't offer many features at all.  [...]  Lua's
> tag method interface is spotty and hard to follow, so unified methods just
> make you think you're getting a whole lot more.  It's an illusion.

Oh, that's hard ;-)  Lua, the language, doesn't offer anything that can't
be done with its VM-code but I wouldn't say that Lua is only an illusions :-)

The fact that you get an additional namespace does make a difference,
especially for objects, that don't have a namespace in its own.  The
uniform access to application methods and tag methods and that for all
data types can help a lot.  Sure, you could get the functionality with
current Lua but under what costs?  Try to implement additional methods
for userdata objects that already implement some within the C lib...

Ciao, ET.

Reply | Threaded
Open this post in threaded view
|

RE: false [was: The "Is nil present in a table" problem}

Alex Moon
In reply to this post by Edgar Toernig
Title: RE: false [was: The "Is nil present in a table" problem}

True, but Scheme also has a symbol type which allows it to have a distinct value for true (#t).  The symbol type also makes things like enumerations alot nicer to work with, and is one of the few things from Scheme I really miss in Lua.

--
Alex R. Moon
[hidden email]
http://www.mailcode.com
 

> -----Original Message-----
> From: John Belmonte [[hidden email]]
> Sent: Wednesday, November 28, 2001 11:26 AM
> To: Multiple recipients of list
> Subject: Re: false [was: The "Is nil present in a table" problem}
>
>
> Paul Chakravarti wrote:
> > I would prefer that this explicitly evaluated to a
> > distinct 'true' type - if there is no explicit 'true' value
> > it is impossible to correctly serialise the value for
> > an API which expects a destinct boolean value (in
> > this case specifically XMLRPC but generally true) by
> > checking the type.
>
> Scheme is a pretty serious as far as languages go and it
> manages to get by
> with just a false type.
>
> Maybe expecting tables (or the language) to support full marshaling
> out-of-the-box is too much.  There are still cases where you
> want some type
> associated with each field but want to allow for nil values. 
> For example
> field "email_address" is a string but it happens to be nil
> right now meaning
> it's invalid or undefined.  When you need that you're back to
> Rici Lake's
> table of tables technique.
>
> -John
>
>

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

David Jeske-3
In reply to this post by John Belmonte-2
On Thu, Nov 29, 2001 at 01:25:57AM +0900, John Belmonte wrote:
> Scheme is a pretty serious as far as languages go and it manages to get by
> with just a false type.

Lua could get away without a false type, if we did away with the "nil
deletes a table entry" and the "standard table entry access returns
nil when not present".

My scheme is rusty, but I'm quite sure it does not overload all those
things onto the false type.

> Maybe expecting tables (or the language) to support full marshaling
> out-of-the-box is too much.  There are still cases where you want some type
> associated with each field but want to allow for nil values.  For example
> field "email_address" is a string but it happens to be nil right now meaning
> it's invalid or undefined.  When you need that you're back to Rici Lake's
> table of tables technique.

This false/nil stuff breaks more than just XML/RPC. I've had trouble
doing proto-inheritence with it. Imagine you are a subclass of
someone. He has the property "a=1", you want to set a local value
"a=nil". Oops.. you can't do that, because you can't store nil. 

There are many things I wish were different in Lua. I wish there were
real exceptions, I don't like the string formatting, and I'm sure
there are a handful of other things I would change if I really
cared. However, this false/nil thing is the only part of Lua which I
consider a broken wart.

(of course I like Lua anyhow, but it would be nice if this were fixed)


-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Russell Y. Webb
In reply to this post by Edgar Toernig
The idiom of nil meaning false *is* a bit strange (but no stranger than 0
meaning false in C).  Just for my own programming sanity I usually use 1==1
and 1==0 to stand for true and false so that my code makes the assumption
that all the comparison operations return the same thing for true and false
(obviously that may be broken), and I try not to think about what that value
is.  

That way a function that needs to return a boolean value will have lines
like 'return 1==1' for returning true.

I've also taken to making the test against nil explicit for existence tests,
as in 
while t[i]~=nil do ... end

For one thing, coding like this is compatible with the introduction of a
boolean type.

Russ


Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Paul Chakravarti
In reply to this post by John Belmonte-2
John Belmonte writes:

Maybe expecting tables (or the language) to support full marshaling
out-of-the-box is too much.  There are still cases where you want some type
associated with each field but want to allow for nil values.  For example
field "email_address" is a string but it happens to be nil right now meaning
it's invalid or undefined.  When you need that you're back to Rici Lake's
table of tables technique. -John

I agree that this isnt a complete solution to the typing problem
however it does help with this particular problem and (IMHO)
makes the API a bit more orthogonal without much additional impact
(if we are already modifying relational operators to support 'false')
and as far as I can tell has no impact on the language semantics.
>From a pragmatic standpoint I dont see a good reason not to include
this. Regards, PaulC

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Edgar Toernig
In reply to this post by Paul Chakravarti
Paul Chakravarti wrote:
> 
> Edgar Toernig writes:
> >
> > And then define that if/while/not/... only accept 'false' and 'true'?
> > I thought about it myself but IMHO it complicates things more than
> > it would help.
> 
> I dont think that this is necessary - all non nil/false values can
> still be treated as true - this is just a specialisation of the
> inplementation to include a 'true' class which is returned by
> relational operators (and can be explicitly assigned)

But that would result in two classes of behaviour: one only accepts
true and another that accepts anything but nil/false.  I'm not sure
that I would like that...

Ciao, ET.

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Paul Chakravarti
Edgar Toernig writes:

But that would result in two classes of behaviour: one only accepts
true and another that accepts anything but nil/false.  I'm not sure
that I would like that...

I am not sure I understand this concern - do you have an example ?
I dont think that this impacts the semantics of relational
operators other than that it is possible to test a type and
tell that it is a 'true' value (from a relational opeartor) -
almost all other code could just ignore this - ie. following
the pattern from the proposal - - true/false are distinct types
print(type(true)) = "true"
print(type(false)) = "false" - Relational operators return true/false
5 > 6         ==> false
1 == 1        ==> true
nil == false  ==> false
1 == true ==> false - Logical operators treat true as a non-nil type
true and 10   ==> true
10 and true   ==> true
10 or true    ==> 10
10 and 11     ==> 11
nil or nil    ==> nil
not(true)     ==> false
not(1)        ==> false
not(false) ==> true Regards, PaulC

Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem]

Roberto Ierusalimschy-5
In reply to this post by John Belmonte-2
On Thu, 29 Nov 2001, John Belmonte wrote:

> Scheme is a pretty serious as far as languages go and it manages to get by
> with just a false type.

Scheme treats any non #f value as "true" in conditionals. But it has a
boolean type (as far as Scheme has any type), with two values: #t and #f.

(see Revised(4) Report on the Algorithmic Language Scheme, Section 6.1:
Booleans; or Revised(5)... Section 6.3.1)

-- Roberto



Reply | Threaded
Open this post in threaded view
|

Re: unified methods

Roberto Ierusalimschy-5
In reply to this post by John Belmonte-2
On Thu, 29 Nov 2001, John Belmonte wrote:

> Actually unified methods doesn't offer many features at all.  It's just
> taking Lua's internal tag method system an exposing it as tables (this is
> why Edgar was shocked by your comment about everything-as-tables).  Lua's
> tag method interface is spotty and hard to follow, so unified methods just
> make you think you're getting a whole lot more.  It's an illusion.

I think it is important to separate unified methods in two quite
independent parts: the first part is keeping tag methods in a table (what
you call "exposing it as tables"); but there is a the second part: to look
into this table for "methods" when you use the syntax a:foo().

(The first part is actually simpler than the current tag system, and we are
considering adopting it in the next version of Lua. It is very easy to
implement the current system using the new one; and we will do it, to keep
compatibility).

-- Roberto


Reply | Threaded
Open this post in threaded view
|

RE: unified methods

Joshua Jensen
> I think it is important to separate unified methods in two 
> quite independent parts: the first part is keeping tag 
> methods in a table (what you call "exposing it as tables"); 
> but there is a the second part: to look into this table for 
> "methods" when you use the syntax a:foo().
> 
> (The first part is actually simpler than the current tag 
> system, and we are considering adopting it in the next 
> version of Lua. It is very easy to implement the current 
> system using the new one; and we will do it, to keep compatibility).

When I made the LuaState distribution's method table support, I misnamed
it as "unified methods" when, in fact, it was method tables that hoped
to one day become unified methods.  But the benefits of method tables
and unifying the tag methods are entirely different.

At no cost to the original implementation of Lua, method tables can:

* Make every data type look like an object by attaching a table of
methods.  This is somewhat like C#'s "boxing" concept.
* Remove the need to implement the gettable tag which must be assigned
to a userdata object.
* Save massive amounts of memory by sharing the same method table among
multiple objects.  This is as opposed to the current table mechanism
where every table has to have a copy of the functions.
* To C++ users, this looks more like the v-tables they're accustomed to.

Unified methods, on the other hand, are there for the unification of tag
methods with the method tables.  If method tables exist, then the tag
methods, IMO, make the most sense in the method tables.  The biggest
benefit unified tag methods provide is removal of the complexities of
tag and tag method management.  If you can work with a method table, you
automatically get tag methods.

More than anything else, though, having Lua adopt method tables is very
important, in my opinion.  But Lua should NOT change the : (colon)
function calling operator to remove the self parameter and only call out
of method tables like Edgar did.  I believe it is important to
distinguish between a regular table function call and a method table
function call.  The LuaState distribution does this by introducing the
-> (like the colon but for method tables) and the :: (like a regular .
Period table lookup).

Josh




Reply | Threaded
Open this post in threaded view
|

Re: unified methods

RLak
In reply to this post by John Belmonte-2


Roberto Ierusalimschy escribió:

> I think it is important to separate unified methods in two quite
> independent parts: the first part is keeping tag methods in a table (what
> you call "exposing it as tables"); but there is a the second part: to
look
> into this table for "methods" when you use the syntax a:foo().

> (The first part is actually simpler than the current tag system, and we
are
> considering adopting it in the next version of Lua. It is very easy to
> implement the current system using the new one; and we will do it, to
keep
> compatibility).

Actually, I think there is another take on this. The following are unedited
thoughts written just before going to lunch, and I won't be offended if
anyone thinks that they were actually out to lunch. Still, you never know,
it might spark some interesting debate.

As I understand it from the correspondence (and no doubt Edgar will correct
me if I'm wrong), in his unified methods implementation,

a:foo(x)

is "syntactic sugar" for:

methods(a).foo(a,x)

where methods(a) is some sort of metamethod, I would guess. (Or perhaps it
works recursively, which might be cool if confusing.)

Another alternative would be for

a:foo

to be "syntactic sugar" for:

curry1(methods(a), a)

where curry1 is a language primitive whose behaviour is defined by:

function(fn, arg) return function(...) return call (fn, tinsert(arg, 1,
args) or args) end end

(I think there is a better way of writing that in 4.1. The irritating "or
args" compensates for tinsert not returning it's first argument.)

It is easy enough to imagine an efficient implementation of this. To start
with, one could implement curry1 as a language primitive (or even the more
general version which accepts more than one curried argument); it would
essentially be the 4.0 implementation of C-closures with the closures
arguments showing up at the bottom of the stack instead of the top.

A further improvement would be for the compiler to recognise a:foo(x, y, z)
and optimise away the creation of the curried function.

Really, this makes the : in a:foo a pseudo-operator with a known and simple
optimisation rather than "syntactic sugar" (that is, it buries the
definition of the operator "methods"). Personally, I might choose a
different symbol for this operator to avoid confusing it with any current
definition of ":". At the risk of offending someone's sensibilities, I'll
write it as "->". It's a pseudo-operator in the sense that "." is a
pseudo-operator; that is, its right-hand argument is a literal.

Now,

a.foo     is defined as  a["foo"]

and

a[x] is defined as  gettable_event(a, x)
a[x] = v  is defined as  settable_event(a, v, x)

So, by analogy,

a->foo    is defined as  a<<"foo">>

(I originally wrote that as a«"foo"» but guillemots are not so easy to
type)

and

a<<x>>         is defined as  getmethod_event(a, x)
a<<x>> = v     is defined as  setmethod_event(a, v, x)

Taking this additional step makes the optimisation referred to above a
little harder to do, since we can no longer rely on a->x returning a curry.
We could make the optimisation explicit by additionally defining:

a<<x>>(args)   is defined as  callmethod_event(a, x, args)

although I find this a little unpleasant because the whole point of this
idea was to do away with special-casing method calls. Instead, we could
still optimise by verifying whether a<<x>> (or a->foo) returned a curry,
and if so immediately expanding it onto the stack before appending the
remaining arguments; this would result in the curry being created and soon
destroyed, but it would avoid a bit of stack shuffling. Alternatively, one
could simply not worry about it.

Is this useful? ... I think so, but any examples will have to wait...

R.



Reply | Threaded
Open this post in threaded view
|

Re: unified methods

Russell Y. Webb
In reply to this post by Joshua Jensen
Thanks for the good description.

> function call.  The LuaState distribution does this by introducing the
> -> (like the colon but for method tables) and the :: (like a regular .
> Period table lookup).

That seems strange.  Why is the double colon not the extension of the colon
operator and the -> a version of the . (like in C)?

Russ


Reply | Threaded
Open this post in threaded view
|

RE: unified methods

Luiz Henrique de Figueiredo
In reply to this post by John Belmonte-2
>* Save massive amounts of memory by sharing the same method table among
>multiple objects.  This is as opposed to the current table mechanism
>where every table has to have a copy of the functions.

The current tag method mechanism implemented in Lua is based on tags.
Objects have tags not tables.
--lhf

Reply | Threaded
Open this post in threaded view
|

RE: unified methods

Joshua Jensen
In reply to this post by Russell Y. Webb
> > function call.  The LuaState distribution does this by 
> introducing the
> > -> (like the colon but for method tables) and the :: (like 
> a regular .
> > Period table lookup).
> 
> That seems strange.  Why is the double colon not the 
> extension of the colon operator and the -> a version of the . 
> (like in C)?

Just in case I was unclear:

table::function() passes no implicit self and would be the same as:

methods(table).function()

table->function() passes an implicit self and would be the same as:

methods(table):function()

That's all there is to it.  The use of the :: and -> operator is just to
mask the methods(table) lookup.

I am unsure exactly of what you were asking, but the :: operator is like
the C++ :: operator and the -> operator is like the C++ . or ->
operators.

Josh




Reply | Threaded
Open this post in threaded view
|

Re: unified methods

Russell Y. Webb
> Just in case I was unclear:
> 
> table::function() passes no implicit self and would be the same as:
> 
> methods(table).function()
> 
> table->function() passes an implicit self and would be the same as:
> 
> methods(table):function()
> 
> That's all there is to it.  The use of the :: and -> operator is just to
> mask the methods(table) lookup.
> 
> I am unsure exactly of what you were asking, but the :: operator is like
> the C++ :: operator and the -> operator is like the C++ . or ->
> operators.

I see.  I guess that illustrates how hard it can be to understand a lot of
interrelated syntaxes.

I was thinking that just by extending the Lua syntax
table::function() -> methods(table):function()
That way the new colon syntax is related to the old mnemonically.  From the
C++ perspective your way makes sense, but I don't think asking people to
remember syntax with reference to C++ is a good thing.

Too bad .. is concatenation or you could use t..x and t::x to mean
methods(t).x and methods(t):x respectively.

Russ


Reply | Threaded
Open this post in threaded view
|

RE: unified methods

Joshua Jensen
> I was thinking that just by extending the Lua syntax
> table::function() -> methods(table):function()
> That way the new colon syntax is related to the old 
> mnemonically.  From the
> C++ perspective your way makes sense, but I don't think 
> asking people to
> remember syntax with reference to C++ is a good thing.

Ah, I do like the notion behind that.  I only chose what I did because
the C++ style was on my mind, that's all.

> Too bad .. is concatenation or you could use t..x and t::x to 
> mean methods(t).x and methods(t):x respectively.

Yeah, this wouldn't be as nice.  Obviously, if method tables were
adopted into Lua, some discussion would be in order to determine the
correct syntax for the calls.

---------------------
And, for what it is worth, here is an implementation of a "method table"
using tags in the current LuaState distribution:

methodTable =
{
	func = function(self)
		print("Hi", self.a)
	end,

	func2 = function()
		print("Hi")
	end
}

methodTable2 = CopyTable(methodTable)

function methodTable2:func3()
	print("Hello", self.b)
end

myTable = { a = 5 }
methods(myTable, methodTable)
myTable::func2()
myTable->func()

myTable2 = { a = 10, b = 20 }

function myTable2:func()
	print("In myTable2:func()", self.b)
end

methods(myTable2, methodTable2)
myTable2::func2()
myTable2:func()				-- Note the difference between
myTable2->func()				-- these two lines
myTable2->func3()

----------------------------------------------------------
Here is the same "method table" using tags in regular Lua:

methodTable =
{
	func = function(self)
		print("Hi", self.a)
	end,

	func2 = function()
		print("Hi")
	end
}

methodTable2 = CopyTable(methodTable)

function methodTable2:func3()
	print("Hello", self.b)
end

----
function myTable_index(table, index)
	return methodTable[index]
end

function myTable2_index(table, index)
	return methodTable2[index]
end

tableTag = newtag()
settagmethod(tableTag, "index", myTable_index)

myTable = { a = 5 }
settag(myTable, tableTag)

myTable.func2()
myTable:func()

table2Tag = newtag()
settagmethod(table2Tag, "index", myTable2_index)

myTable2 = { a = 10, b = 20 }

function myTable2:func()
	print("In myTable2:func()", self.b)
end

settag(myTable2, table2Tag)

myTable2.func2()
myTable2:func()
myTable2:func3()

--------------------------------------------------------------

The biggest difference between the two is speed.  In order for the index
tag method to be called, the VM has to first determine that func, func2,
or func3 isn't in the table.  Then it sets up all state to call the tag
method, makes the function call, which causes another virtual machine
execution, and finally retrieves the value.

In the method table syntax, no tag methods are called and you already
explicitly told the VM to look in the method table.  In fact, LuaState's
implemention of the VM instructions for the method table actually end up
being a touch faster than a regular table lookup.

One more item of note is the fact that myTable2 contains a function
called func().  So does the method table.  In the tag method setup,
there is no way to call the method table's func().  They are easily
distinguished between with the method table.

Josh



Reply | Threaded
Open this post in threaded view
|

Re: false [was: The "Is nil present in a table" problem}

Thomas Wrensch-2
In reply to this post by David Jeske-3
Hello all,

I've been following the "problems with nil" thread here with great
interest.

It seems as if there are two major problems with the various uses of nil
in Lua: its use in place of a boolean false value, and its use to
represent table members that are not there. Adding a false (and possibly a
true) value to the set of values directly supported by lua would fix only
the first problem.

There is a similar, though somewhat less sever, problem in Smalltalk.
There are times when it is important to differentiate between a variable
that contains a default value and one that contains no value at all. The
solution in Smalltalk/V was to add an EmptySlot class and associated
value.

It may be worthwhile to consider this as a possible solution to the
problem of using nil to show empty slots. This requires some thought:
while adding a new false value and type is a relatively small change to
Lua, splitting nil's use as a default value and empty slot value would
break a lot of code. Maybe someone with more Lua experience can come up
with a way that fits the language better.


  - Tom Wrensch



123