getn

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

getn

Alberto Demichelis
Title: Message
Hi all,
I've got a simple question.
I'm storing into a table several items(other tables) using a numerical index as key
and I would like to know how many elements are into the table.So I tryed with lua_getn();
The problem is that I'm not inserting sorted elements, for instance if I insert the first element with
key 8 getn() will return 8.
 
Is there any way to have the real number of "non nil" elements?
 
thanks for your time
 
-------------------------------
Alberto Demichelis
Crytek Studios GmbH
------------------------------
 
Reply | Threaded
Open this post in threaded view
|

RE: getn

Nick Trout-4
>>I've got a simple question.
I'm storing into a table several items(other tables) using a numerical index
as key
and I would like to know how many elements are into the table.So I tryed
with lua_getn();
The problem is that I'm not inserting sorted elements, for instance if I
insert the first element with
key 8 getn() will return 8.
Is there any way to have the real number of "non nil" elements?

Write your own! :o)

getn returns the highest numerical key. Have a look in the manual.

nick

Reply | Threaded
Open this post in threaded view
|

RE: getn

Alberto Demichelis
I had a look in the manual this is why I'm asking if there is another
common solution! :O)

-----Original Message-----
From: Nick Trout [[hidden email]] 
Sent: Wednesday, February 27, 2002 6:04 PM
To: Multiple recipients of list
Subject: RE: getn



>>I've got a simple question.
I'm storing into a table several items(other tables) using a numerical
index as key and I would like to know how many elements are into the
table.So I tryed with lua_getn(); The problem is that I'm not inserting
sorted elements, for instance if I insert the first element with key 8
getn() will return 8. Is there any way to have the real number of "non
nil" elements?

Write your own! :o)

getn returns the highest numerical key. Have a look in the manual.

nick

Reply | Threaded
Open this post in threaded view
|

RE: getn

Thomas Wrensch-2
In reply to this post by Nick Trout-4
One way to do this in Lua:

    function tsize(t)
        local c = 0
        for k,v in t do c=c+1 end
        return c
    end

There doesn't seem to be anything built into the C API for doing this
directly. I poked around a bit in ltable.c and ltable.h and don't see any
obvious way to get the information. I'd look a bit more, but I have a
class to teach now.

  - Tom Wrensch



On Wed, 27 Feb 2002, Nick Trout wrote:

> 
> >>I've got a simple question.
> I'm storing into a table several items(other tables) using a numerical index
> as key
> and I would like to know how many elements are into the table.So I tryed
> with lua_getn();
> The problem is that I'm not inserting sorted elements, for instance if I
> insert the first element with
> key 8 getn() will return 8.
> Is there any way to have the real number of "non nil" elements?
> 
> Write your own! :o)
> 
> getn returns the highest numerical key. Have a look in the manual.
> 
> nick
> 


Reply | Threaded
Open this post in threaded view
|

RE: getn

Reuben Thomas
>     function tsize(t)
>         local c = 0
>         for k,v in t do c=c+1 end
>         return c
>     end

...which is a generalisation of the neat little trick to find if a table
is empty:

function empty(t)
  for _, _ in t do
    return nil
  end
  return 1
end

-- 
http://www.mupsych.org/rrt/ | Slow Pedestrian Crossing


Reply | Threaded
Open this post in threaded view
|

RE: getn

Nick Trout-4
In reply to this post by Alberto Demichelis
> 
> I had a look in the manual this is why I'm asking if there is another
> common solution! :O)

Aha! I think the basic idea is... Lua comes as a bare skeleton and if you
want more you are free to do as you please. getn() comes so you can retrieve
n from arg lists and various places that come with the vanilla build. If
you'd like a neopolitan build then you could scour the sample code in the
wiki? You could look at the Python list and dictionary emulation for some
code? A more common solution may emerge from the Lua standard libraries.

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

Reuben, nice ideas, perhaps we should have a Lua Gems page?!

Nick


Reply | Threaded
Open this post in threaded view
|

RE: getn

Reuben Thomas
> Reuben, nice ideas, perhaps we should have a Lua Gems page?!

Better just some libraries for people to look at. I should put something
up; unfortunately I'm rather busy until the end of the week when I
disappear for two weeks with no net access. I'll try to do something about
it soon after I get back; my plan was just to upload the current state of
my libraries to somewhere on lua-users.org, and allow the feeding frenzy
to start.

-- 
http://www.mupsych.org/rrt/ | frog, n.  a prince waiting for the right kiss


Reply | Threaded
Open this post in threaded view
|

RE: getn

Curt Carpenter
In reply to this post by Nick Trout-4
It's worth considering as a feature request that all tables have an
implicit member, called something like _rows, which is the number of
rows in the table. Or at least a new function like GetLength() or
something. This seems incredibly useful, and would be a boon for
performance for people that need to know these sorts of things without
iterating over all table elements all the time (or having to modify
tables they don't own to cache it). Lua already has this information
readily available. Why not expose it?

Curt

Reply | Threaded
Open this post in threaded view
|

RE: getn

Luiz Henrique de Figueiredo
In reply to this post by Nick Trout-4
>Lua already has this information readily available. Why not expose it?

Lua does not have this information readily available. It only has the size of
the hash table, which is unrelated to the number of non-nil entries in it.

>This seems incredibly useful, and would be a boon for
>performance for people that need to know these sorts of things without
>iterating over all table elements all the time (or having to modify
>tables they don't own to cache it).

A simple solution, which has come up in the lengthy discussion about getn in
the past, is to use a separate table to cache this info. You'd use your tables
to index this table and store n in it.
--lhf

Reply | Threaded
Open this post in threaded view
|

RE: getn

Curt Carpenter
In reply to this post by Nick Trout-4
> Lua does not have this information readily available. It only has the
size of the hash table, which is unrelated to the number of non-nil
entries in it.

Ok, sorry, I assumed it did, which looked to be the case from a casual
glance at some of the sources.

> A simple solution, which has come up in the lengthy discussion about
getn in the past, is to use a separate table to cache this info. You'd
use your tables to index this table and store n in it. --lhf

I don't see this as a good solution. It means that you have to have a
tag method to support it. Which means you can't reuse code that relies
on it, since you don't own the tag method for all tables you might
operate on. And then there's the perf issue I keep coming back to. Lua
could be much more performant by keeping a count of elements without any
extra tag method lookups, function calls, and more table lookups. Maybe
I'm in the minority, but performance is a very critical facet of the
language for me. It seems that anything which is broadly applicable and
useful, and can be done in a generic way internally in Lua much faster
than you can on top of Lua is a good thing.

Curt

Reply | Threaded
Open this post in threaded view
|

Re: getn

Björn De Meyer
Curt Carpenter wrote:
> And then there's the perf issue I keep coming back to. Lua
> could be much more performant by keeping a count of elements without any
> extra tag method lookups, function calls, and more table lookups. Maybe
> I'm in the minority, but performance is a very critical facet of the
> language for me. It seems that anything which is broadly applicable and
> useful, and can be done in a generic way internally in Lua much faster
> than you can on top of Lua is a good thing.
> 
> Curt

Yes, but the performance issue cuts both ways. The most simple 
way to keep the count in Lua internally would be to 
add an internal "element_count" variable to each table. 
However, in that case, for each addition or deletion of an element 
to th table, you need to update this internal variable. This
does not sound like much, but what if you have a data table of 
thousands of elements?  

By not keeping track of the amount of elements in a table
internally, you gain some performance whilst adding and deleting 
elements. The price to pay for that is that you will need to perform 
a full table walk to count the amount of elements. The question is, 
"What will be done most frequently?" Adding and removing
table elements, or counting the amount of table elements?

I am inclined to think that table element addition/removal is much
more common. I have no evidence of this, however, so it is merely
my gut feeling. If anyone has any numbers about this, I would be 
interested.

Performance is always a matter of sacrifices. 
You should alays beware not to make a big sacrifice 
for a small gain in speed.


-- 
"No one knows true heroes, for they speak not of their greatness." -- 
Daniel Remar.
Björn De Meyer 
[hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: getn

Curt Carpenter
In reply to this post by Nick Trout-4
> Yes, but the performance issue cuts both ways. The most simple 
> way to keep the count in Lua internally would be to 
> add an internal "element_count" variable to each table. 
> However, in that case, for each addition or deletion of an element 
> to th table, you need to update this internal variable. This does not 
> sound like much, but what if you have a data table of 
> thousands of elements?  

It doesn't matter how many elements are in the table. In fact when the
table is huge is exactly when it's MORE important for Lua to own the
size for you so people don't unwittingly iterate over huge tables just
to get their size. Incrementing/decrementing an int is like a couple
machine instructions and is absolutely not even on the performance radar
in terms of all the other stuff going on to add/remove an element from a
table. I would wager you couldn't even measure the perf difference.

Curt

Reply | Threaded
Open this post in threaded view
|

RE: getn

Thomas Wrensch-2
On Wed, 27 Feb 2002, Curt Carpenter wrote:

> > Yes, but the performance issue cuts both ways. The most simple 
> > way to keep the count in Lua internally would be to 
> > add an internal "element_count" variable to each table. 
> > However, in that case, for each addition or deletion of an element 
> > to th table, you need to update this internal variable. This does not 
> > sound like much, but what if you have a data table of 
> > thousands of elements?  
> 
> It doesn't matter how many elements are in the table. In fact when the
> table is huge is exactly when it's MORE important for Lua to own the
> size for you so people don't unwittingly iterate over huge tables just
> to get their size. Incrementing/decrementing an int is like a couple
> machine instructions and is absolutely not even on the performance radar
> in terms of all the other stuff going on to add/remove an element from a
> table. I would wager you couldn't even measure the perf difference.

Sounds like what we need is someone to hack to source and try it, then do
some performance measurements. I'll do it, but not until the end of March,
my time is too full between now and then.

  - Tom Wrensch


Reply | Threaded
Open this post in threaded view
|

Metatables

Eric Tetz-2
In reply to this post by Curt Carpenter
I'm using Lua to replace a scripting language (which I'll call FOO) in an existing application. 
For the most part, translating FOO scripts into Lua is trivial, but there a few cases where FOO's
semantics are different enough to make my life difficult.  The first is that variables need not
exist before they are used in an expression. For instance:

  x = x + 1

In FOO, when x is encountered in the rhs expression and found not to exist, it is created and
initialized to 0.  After this statement, x will have the value 1.

I can emulate this behavior in Lua with:

  metatable (
    globals(), {
    index = function(t,k) 
      rawset(t,k,0) 
      return 0 
    end,
    })

The second situation is:

  a[0] = 1

Again, in FOO, if 'a' does not exist before this statement, it is created.  I can emulate this
with:

  metatable (
    globals(), {
    index = function(t,k) 
      local nt = {}
      rawset(t,k,nt) 
      return nt 
    end,
    })

My problem is that I can't have both. I've resigned myself to choosing one or the other, and
trying to fix the other case some other way... but I thought I would post here first, in case
someone knows a trick that would let me have my cake and eat it, too. ;)

Cheers,
Eric


__________________________________________________
Do You Yahoo!?
Yahoo! Greetings - Send FREE e-cards for every occasion!
http://greetings.yahoo.com

Reply | Threaded
Open this post in threaded view
|

Re: Metatables

Luiz Henrique de Figueiredo
>I'm using Lua to replace a scripting language (which I'll call FOO) 

Perhaps FOO == awk ?

>My problem is that I can't have both.

Yes, you can, but it's not so simple.
Try this: define the index method for globals to return a special kind
of proxy table, one for which methods are defined to handle arithmetic and
indexing. When you create these proxy tables in the index method for the
global table, store the name of the variable. Later, when the value is used
as a number, the variable becomes an ordinary global variable with a number
value (you do this in the getglobal method for globals, and looking at the
metatable of the value to see whether it is a proxy table). Similarly when
the value is used as a table, but in this case it is easier because you
only have to use the index method for the proxy. Again, you can then "convert"
the proxy into a true value. Or you might keep both options (and then you'll
be cloning the behaviour of awk, which allows a=0 and a[0]=1 simultaneously).

Sorry for the long, text-only explanation, and no code...
Anyway, I hope it helps.
--lhf

Reply | Threaded
Open this post in threaded view
|

Re: Metatables

James Hearn
> >I'm using Lua to replace a scripting language (which I'll call FOO)
>
> Perhaps FOO == awk ?
>
> >My problem is that I can't have both.
>
> Yes, you can, but it's not so simple.
> Try this: define the index method for globals to return a special kind
> of proxy table, one for which methods are defined to handle arithmetic and
> indexing. When you create these proxy tables in the index method for the
> global table, store the name of the variable. Later, when the value is used
> as a number, the variable becomes an ordinary global variable with a number
> value (you do this in the getglobal method for globals, and looking at the
> metatable of the value to see whether it is a proxy table). Similarly when
> the value is used as a table, but in this case it is easier because you
> only have to use the index method for the proxy. Again, you can then "convert"
> the proxy into a true value. Or you might keep both options (and then you'll
> be cloning the behaviour of awk, which allows a=0 and a[0]=1 simultaneously).
>
> Sorry for the long, text-only explanation, and no code...
> Anyway, I hope it helps.
> --lhf

If I understand, this is a way to "delay" deciding what the value of 'a' is
until it's used in an expression? I've done a similar thing in the past with
NebLUA. It worked pretty well within the scope of that project.

--James Hearn


Reply | Threaded
Open this post in threaded view
|

Re: Metatables

Eric Tetz-2
In reply to this post by Luiz Henrique de Figueiredo
--- Luiz Henrique de Figueiredo <[hidden email]> wrote:
> Try this: define the index method for globals to return a special kind
> of proxy table, one for which methods are defined to handle arithmetic and
> indexing.

Beautiful. ;) More than I hoped for. It neatly solves another problem I had: the need to
distinguish between x + y and x .. y.

> Anyway, I hope it helps.

Tremendously.

Cheers,
Eric

__________________________________________________
Do You Yahoo!?
Yahoo! Greetings - Send FREE e-cards for every occasion!
http://greetings.yahoo.com

Reply | Threaded
Open this post in threaded view
|

RE: Metatables

John Passaniti-4
> Beautiful. ;) More than I hoped for. It neatly solves
> another problem I had: the need to distinguish
> between x + y and x .. y.

For the more mentally sluggish (like me), when you implement what Luiz
suggested, could you post the code?



Reply | Threaded
Open this post in threaded view
|

offtopic on awk [was: Re: Metatables]

David Jones-2
In reply to this post by Luiz Henrique de Figueiredo
In message <200202280003.VAA08283@...>, Luiz Henrique de Fig
ueiredo writes:
> Perhaps FOO == awk ?
> 
> (and then you'll
> be cloning the behaviour of awk, which allows a=0 and a[0]=1 simultaneously).

GNU awk may allow that but it is not standard.

Line 6068 - 6069 of IEEE Std 1003.1-2001 "Standard for Information
Technology Portable Operating System Interface (POSIX) Shell and
Utilities, Issue 6" (the bit describing the behaviour of awk) says:

  The same name shall not be used within the same
  scope both as a scalar variable and as an array.

Cheers,
 drj

Reply | Threaded
Open this post in threaded view
|

RE: Metatables

Eric Tetz-2
In reply to this post by John Passaniti-4
--- John Passaniti <[hidden email]> wrote:
> For the more mentally sluggish (like me), when you implement what Luiz
> suggested, could you post the code?

Sure, though it's somewhat specific to my app. For one thing, I don't worry about 'gettable' on a
proxy, because that situation never occurs in the mechanically translated FOO scripts.


local is_proxy, 
  proxy_tonum, 
  proxy_tostr, 
  proxy

function is_proxy(p)
  return type(p) == "table" and metatable(p) == proxy_metatable
end

function proxy_tonum(p)
  if is_proxy(p) then
    setglobal(p.name, 0)
    return 0
  else
    return p
  end
end

function proxy_tostr(p)
  if is_proxy(p) then
    setglobal(p.name, "")
    return "" 
  else
    return p
  end
end

proxy_metatable = {
  add = function(l,r) return proxy_tonum(l) + proxy_tonum(r) end,
  sub = function(l,r) return proxy_tonum(l) - proxy_tonum(r) end,
  mul = function(l,r) return proxy_tonum(l) * proxy_tonum(r) end,
  div = function(l,r) return proxy_tonum(l) / proxy_tonum(r) end,
  pow = function(l,r) return proxy_tonum(l) ^ proxy_tonum(r) end,
  unm = function(o) setglobal(o.name, 0) return 0  end, 
  concat = function(l,r) return proxy_tostr(l) ..proxy_tostr(r) end,
  settable = function(t,k,v) 
    local nt = {}
    rawset (nt, k, v)
    setglobal (t.name, nt)
  end,
}

metatable (
  globals(), {
  index = function(t,k) 
    local proxy = { name = k }
    metatable (proxy, proxy_metatable)
    rawset (t, k, proxy) 
    return proxy 
  end,
  })


-- Try it out...

a = b + 1 + -c * d
e = f / 1 ^ g
h = i .. "str"
j[1] = "one"

print (a, b, c, d, e, f, g, h, i, j[1])


__________________________________________________
Do You Yahoo!?
Yahoo! Greetings - Send FREE e-cards for every occasion!
http://greetings.yahoo.com

12