Application of indexing to all types

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

Application of indexing to all types

Doug Rogers-4

I've been thinking, which isn't a good sign...

On another thread I mentioned that I liked the colon notation and wished that it could be applied to all types; PA disagreed, using dental care for his reasoning. :)

Mike Pall pointed me to the code that handles it along with a suggestion on how to make it work. I will probably play around with it at some point (I'm already spending time away from work I *should* be doing!). For now I just want to discuss it.

I think it would be nice to extend the use of '.' and ':' to all types. I'd like to be able to do something like this:

> s='abcd'
> s:print()
abcd
> print(s:len())
4
> c=coroutine.create(function() print('hey!') end)
> c:resume()
hey!
> n=6
> n:print()
6
>

The last one doesn't help much but I think the other two help with readability - and typing.

I was thinking that each non-table, non-nil type - 'number', 'string', 'thread', 'boolean' - would have its own table with a metatable attached with __index set to that table. This would allow the VM to easily (and quickly) push the table associated with the type onto the stack before attempting to index a non-table type. 'nil' would still result in an error.

In the examples above, the ones that are of the form x:print() would require the use of the global table if the type table did not resolve the name. I'm not so worried about supporting that as I am about things like s:len() mapping to string.len(s). In the 'print' case it may be better for an error to be raised. A developer could always set string.print = print and the system above would work.

I like the idea, and I'm wondering what others think. Am I the only one who loves the colon notation and wishes that it applied to all the built-in types?

By the way, why do we call the library 'coroutine' and the type 'thread', but with string we use 'string' and 'string'? I suspect it is to avoid the name space collisions for 'thread' but to keep the type name shorter than 'coroutine'. Of course the name space argument could certainly be used for 'string'. Unfortunate, since it makes this idea harder to implement.

Thanks to the creators of Lua. It is a thing of beauty, even with these little 'flaws'. :)

Doug

--
--__-__-____------_--_-_-_-___-___-____-_--_-___--____
Doug Rogers - ICI - V:703.893.2007x220 www.innocon.com
-_-_--_------____-_-_-___-_--___-_-___-_-_---_--_-__-_


Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Vat Raghavan
--- Doug Rogers <[hidden email]> wrote:

[snip]
> 
> Thanks to the creators of Lua. It is a thing of beauty, even with these 
> little 'flaws'. :)
> 
> Doug
> 

on that note, i think the Japanese concept of 'wabi sabi' applies perfectly :) 

http://c2.com/w4/wikibase/?WabiSabi


--vat


		
__________________________________ 
Do you Yahoo!? 
Read only the mail you want - Yahoo! Mail SpamGuard. 
http://promotions.yahoo.com/new_mail 

Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Doug Rogers-4
Vat Raghavan wrote:

Thanks to the creators of Lua. It is a thing of beauty, even with these little 'flaws'. :)
on that note, i think the Japanese concept of 'wabi sabi' applies perfectly :) http://c2.com/w4/wikibase/?WabiSabi

Shall we start a Glass Bead Game? (http://www36.pair.com/waldzell/GBG/)

I'm in love with the board game go, an ancient Chinese game which was taken to new heights by Japan over the last few centuries. It is superior to chess on so many levels - at least for those of us who like complexity through simplicity.

 http://www.nihonkiin.or.jp/igf/aboutIGF.htm
 http://www.usgo.org/index.asp
 http://planeta.terra.com.br/esporte/go/

Way off topic, huh? Still so much work to do...

Doug

--
--__-__-____------_--_-_-_-___-___-____-_--_-___--____
Doug Rogers - ICI - V:703.893.2007x220 www.innocon.com
-_-_--_------____-_-_-___-_--___-_-___-_-_---_--_-__-_


Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Vat Raghavan
--- Doug Rogers <[hidden email]> wrote:

> Vat Raghavan wrote:
> 
> >>Thanks to the creators of Lua. It is a thing of beauty, even with these 
> >>little 'flaws'. :)
> >>    
> >>
> >on that note, i think the Japanese concept of 'wabi sabi' applies perfectly
> :) 
> >http://c2.com/w4/wikibase/?WabiSabi
> >  
> >
> 
> Shall we start a Glass Bead Game? (http://www36.pair.com/waldzell/GBG/)
> 
> I'm in love with the board game go, an ancient Chinese game which was 
> taken to new heights by Japan over the last few centuries. It is 
> superior to chess on so many levels - at least for those of us who like 
> complexity through simplicity.
> 
>   http://www.nihonkiin.or.jp/igf/aboutIGF.htm
>   http://www.usgo.org/index.asp
>   http://planeta.terra.com.br/esporte/go/
> 
> Way off topic, huh? Still so much work to do...
> 
> Doug
> 

I agree 100%. when it comes to board games, Go is about as simple and elegant
as you can get. the beauty of Go is that given essentially 4 simple rules you
can get such fascinating, challenging and complex higher order strategy. A game
that takes minutes to learn by a lifetime to master. (Though, really even the
best in the world don't consider themselves a master of the game.) 
I just learnt of Go a few months ago myself, and it captured my heart instantly
:) 

--vat




		
__________________________________ 
Do you Yahoo!? 
Yahoo! Sports - Sign up for Fantasy Baseball. 
http://baseball.fantasysports.yahoo.com/

Reply | Threaded
Open this post in threaded view
|

RE: Application of indexing to all types

Joshua Jensen
In reply to this post by Doug Rogers-4
> Mike Pall pointed me to the code that handles it along with a 
> suggestion on how to make it work. I will probably play 
> around with it at some point (I'm already spending time away 
> from work I *should* be doing!). 
> For now I just want to discuss it.

I posted this in another thread, but let me do it here where it applies more
directly and won't get lost:

LuaPlus does this, if anybody needs full implementation details.  Most is in
ltm.c, but there are a couple extra items in lvm.c, lstate.c/h and possibly
lbaselib.c, as I recall.  And, since LuaPlus also supports wide character
strings, the method of string access is identical, making my life much
easier:

s = "Hello"
print(s:len())
print(s:find("el"))

s = L"Hello"
print(s:len())
print(s:find(L"el"))

I, for one, have found it super convenient, and I would love to see it
rolled into the core one day.

Josh


Reply | Threaded
Open this post in threaded view
|

OP_SELF (was Re: Application of indexing to all types)

Mark Hamburg-4
In reply to this post by Doug Rogers-4
The piece of code of real interest is the code in lvm.c that implements
OP_SELF. Essentially what the language gives you at that point is a target
value and a string. OP_SELF needs to come up with a callable entity (e.g., a
function) and a target.

The existing implementation for OP_SELF is effectively:

    function OP_SELF( obj, msg )
        return obj[ msg ], obj
    end

Examples of alternative implementations would include the __methods
metatable patch which provides a metatable entry akin to __index but
accessed only by the colon operator.

    function metafield( t, k )
        local mt = getmetatable( t )
        return mt and rawget( mt, k )
    end

    function lookup( handler, t, k )
        if handler == nil then
            return nil
        elseif type( handler ) == "table" then
            return handler[ k ]
        else
            return handler( t, k )
        end
    end

    function OP_SELF_methods( obj, msg )

        local f = rawget( obj, msg )

        if f == nil then
            f = lookup( metafield( obj, "__methods" ), obj, msg )
        end

        if f == nil then
            f = lookup( metafield( obj, "__index" ), obj, msg )
        end

        return f, msg
 
    end

If one redefines OP_SELF, then there probably need to be the following
additional enhancements since the necessary information may not be readily
available:

lua_getmethod( lua_State* L ): A C API extension that takes the top two
objects on the stack as obj and msg and does the appropriate method lookup.

bindmethod( obj, msg ): A Lua function that takes an object and a message
and returns a closure that sends msg to obj with any other parameters passed
to the closure.

hasmethod( obj, msg ): A Lua function that tests for the presence of a
message -- i.e., it tells you whether it would be safe to send the message.

Mark


Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Edgar Toernig
In reply to this post by Doug Rogers-4
Doug Rogers wrote:
>
>[...] 
> I like the idea, and I'm wondering what others think. Am I the only one 
> who loves the colon notation and wishes that it applied to all the 
> built-in types?

You're definitely not the only one :-)  The chapter "Method Tables" in

   http://goron.de/~froese/sol/Diffs2Lua

describes how I approached the topic.

Ciao, ET.

Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Doug Rogers-4
In reply to this post by Joshua Jensen
Joshua Jensen wrote:

LuaPlus does this, if anybody needs full implementation details.


Thanks, Josh. I've downloaded LuaPlus to look through the source files.

Doug

--
--__-__-____------_--_-_-_-___-___-____-_--_-___--____
Doug Rogers - ICI - V:703.893.2007x220 www.innocon.com
-_-_--_------____-_-_-___-_--___-_-___-_-_---_--_-__-_


Reply | Threaded
Open this post in threaded view
|

Re: OP_SELF (was Re: Application of indexing to all types)

Mark Hamburg-4
In reply to this post by Mark Hamburg-4
on 2/25/05 9:45 AM, Mark Hamburg at [hidden email] wrote:

> If one redefines OP_SELF, then there probably need to be the following
> additional enhancements since the necessary information may not be readily
> available:
> 
> lua_getmethod( lua_State* L ): A C API extension that takes the top two
> objects on the stack as obj and msg and does the appropriate method lookup.
> 
> bindmethod( obj, msg ): A Lua function that takes an object and a message
> and returns a closure that sends msg to obj with any other parameters passed
> to the closure.
> 
> hasmethod( obj, msg ): A Lua function that tests for the presence of a
> message -- i.e., it tells you whether it would be safe to send the message.

D'oh. I forgot callmethod( obj, msg, ... ). One could define bindmethod as:

    function bindmethod( obj, msg )
        return function( ... )
            return callmethod( obj, msg, ... )
        end
    end

It might still be advantageous to write this in C where the stack
manipulation may be easier or more efficient, but it isn't strictly
required.

Mark


Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Adrian Sietsma
In reply to this post by Doug Rogers-4
Doug Rogers wrote:

I've been thinking, which isn't a good sign...

On another thread I mentioned that I liked the colon notation and wished that it could be applied to all types; ...
For now I just want to discuss it.

I think it would be nice to extend the use of '.' and ':' to all types. ... I was thinking that each non-table, non-nil type - 'number', 'string', 'thread', 'boolean' - would have its own table with a metatable attached with __index set to that table. This would allow the VM to easily (and quickly) push the table associated with the type onto the stack before attempting to index a non-table type. 'nil' would still result in an error.
...
I like the idea, and I'm wondering what others think. Am I the only one who loves the colon notation and wishes that it applied to all the built-in types?

sorry, but nonononononono
one of the things i like about lua is it's first-class objects.
a number is a number. if i want an object, it can be a table.
(how would the lua chip/pda/arm people like every number to have a metatable ?)

as for the colon syntax
a:func(...) <=> a.func(a,...) is a simple enough syntax for me.
the main advantage is that you can say
objects[lookup]:func()
without a local var.

as i see it, the simplest way to generalise the colon operator would be to define
a:func(...) => (a.func or func)(a,...)

put that way, it looks a bit ugly;
i could live with that... but i don't need it,
 and i don't want to contemplate the core changes required.

Adrian

Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Asko Kauppi-3

In fact, I'd very _much_ like a userdata-kind of integer type, which can have metamethods. The thing that all numbers are float/double will cause problems on ARM chips, due to no FPU. :) But that's another story..

27.2.2005 kello 07:03, Adrian Sietsma kirjoitti:

 sorry, but nonononononono
one of the things i like about lua is it's first-class objects.
a number is a number. if i want an object, it can be a table.
(how would the lua chip/pda/arm people like every number to have a metatable ?)


Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Michael Abbott
Asko Kauppi wrote:
In fact, I'd very _much_ like a userdata-kind of integer type, which can have metamethods. The thing that all numbers are float/double will cause problems on ARM chips, due to no FPU. :) But that's another story..

Never mind that most of the ARMs I've worked on have no integral divide instruction. The divide that our compilers generate is very inefficient so we always roll our own (and different ones for different circumstances depending on where you need your accuracy), so you'd want to be able to tell lua to use that division instead if you just replaced lua_Number and recompiled.

But I digress (too ;)...

- Mab

Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Luiz Henrique de Figueiredo
> so you'd want 
> to be able to tell lua to use that division instead if you just replaced 
> lua_Number and recompiled.

In 5.1 you can do that by defining num_div adequately in luaconf.h.
(And the same for all arithmetic operations.)
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Gunnar Zötl
In reply to this post by Doug Rogers-4
DR> I've been thinking, which isn't a good sign...

if you say so... ;-)

DR> I think it would be nice to extend the use of '.' and ':' to all types.
DR> I'd like to be able to do something like this:

I don't feel this would be such a great idea, from a consistency point
of view. Using the colon or dot notation on a table means that you
consider this individual table and its metatable(s) in order to resolve
the table lookup and thus the resulting operation. The lookup of the
required field occurs in the context of the _value_ in question, and
is thus dynamic.

Your proposal would lead to a second, very different meaning for the
colon, namely that the resolution of the table lookup would occur
someplace else. As strings and numbers are immutable values, it would
not make much sense to directly attach a metatable to such a value.
Also, you can not do table lookups on them. So you'd have some global
means to do the required lookup. But then the lookup does not take
place in the context of your value any more. Instead, it happens in
the static environment of the _operation_ in question. Of course, you
could use setfenv() to work around this, but this opens another can of
worms. 

Thus, you'd end up with two meanings of the colon operator, that
differ in both semantics and binding. That's way too much differing
for me to support such a change. 

just my thoughts,

Gunnar




Reply | Threaded
Open this post in threaded view
|

Re: Application of indexing to all types

Doug Rogers-4
Gunnar Zötl wrote:

As strings and numbers are immutable values, it would
not make much sense to directly attach a metatable to such a value.


[I do not follow the reasoning here - why immutability plays a role in whether or not a metatable makes sense. But that's really not at issue to what I've proposed.]

... But then the lookup does not take place in the context of your value any more. ... Thus, you'd end up with two meanings of the colon operator, that differ in both semantics and binding.


Thanks for the comments, Gunnar. Indeed, thanks to all who have commented on this thread.

I wrote a longer version of this, but I've decided to state it briefly (it's long enough):

(1) My original proposal http://lua-users.org/lists/lua-l/2005-02/msg00666.html is more complex than necessary.

(2) My simpler proposal is slightly more than Adrian Sietsma indicated:

 x:func(...) ==> (x.func or _G[type(x)].func or func)(x, ...)

(3) This does not require metatables for the other types.

(4) This *does* require a core change (as in Josh Jensen's LuaPlus).

(5) Some of the global tables needed for (2) already exist in the standard.

(6) Where to place inconsistencies and incompleteness is a matter of taste, and I find it more tasty to have the colon operator applicable to all data types, rather than scoped to the context of the variable and limited in applicability.

(7) I'm after improvements in the total Lua experience, not just The Core.

(8) If the meaning were originally as above, I seriously doubt that many would be arguing to reduce its scope, though they may be arguing for a better implementation (__methods, non-table metatables, etc.).

(9) Clearly there are enough detractors that this won't happen anytime soon. Or, the detractors are of enough stature that it would be silly to argue with them (and I do not mean that in a bad way).

So for now such conveniences as s:len() will be for me and LuaPlus users. Now I've just got to port LuaPlus to Unixy OSes....

Doug

-- colon.lua
-- Colonize your own strings!
-- No Core changes necessary!

function flookup(object, funcname)
  local f

  if (type(object) == 'table') or (type(object) == 'userdata') then
     f = object[funcname]

     if f then
        return f
     end
  end

  if _G[type(object)] then
     f = _G[type(object)][funcname]

     if f then
        return f
     end
  end

  return _G[funcname]
end   -- flookup()

function colonfunc(s)
  local r, n
  r, n = string.gsub(s,
                     '(%w*):(%w*)([(][)])',
                     '(flookup(%1, "%2"))(%1)')

  if n < 1 then
     r, n = string.gsub(s,
                        '(%w*):(%w*)([(])',
                        '(flookup(%1, "%2"))(%1, ')
  end

  return loadstring('return ' .. r)
end   -- colonfunc()

function colonize(s)
  local f = assert(colonfunc(s))
  return f()
end   -- colonize()

$ lua
Lua 5.0.2  Copyright (C) 1994-2003 Tecgraf, PUC-Rio
> dofile'colon.lua'
> s='Lua is colonizing my strings!'
> colonize('s:print()')
Lua is colonizing my strings!
> print(colonize('s:len()'))
29
> print(colonize('s:gsub("%s",":")'))
Lua:is:colonizing:my:strings!   4
>

--
--__-__-____------_--_-_-_-___-___-____-_--_-___--____
Doug Rogers - ICI - V:703.893.2007x220 www.innocon.com
-_-_--_------____-_-_-___-_--___-_-___-_-_---_--_-__-_