NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 12:08 PM |
Here's a neat code snippet:
function array(t) return setmetatable(t, { __call = function(self, _, key) return next(self, key) end }) end
And here's how you use it:
local t = array {1, 3, 3, 7} for k, v in t do print(k, v) end
Look ma, no `pairs`! |
|
|
| Report Abuse |
|
|
|
| 01 Nov 2011 12:11 PM |
| Thats too complex, it belongs to some other subforum. |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 12:15 PM |
For reasons which are much more complex, it's not possible to allow the following in a threadsafe way:
for v in t do print(v) end
The issue is that lua passes the first variable (the key) of one iteration to the next iteration, allowing me to use `next`. Without `next`, I need to somehow store the iterator state somewhere - unfortunately, there is nowhere I can store it specific to that loop. |
|
|
| Report Abuse |
|
|
|
| 01 Nov 2011 12:45 PM |
| what exactly does "pairs()" return? |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 12:47 PM |
| I think pairs returns `next, t, nil` |
|
|
| Report Abuse |
|
|
|
| 01 Nov 2011 12:48 PM |
I disliek for loops theyre too complex.
Is the pairs function called each time to for loop loops or wat? |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 03:01 PM |
| No, the `pairs` function is only called once. The function returned by the pairs function is called multiple times. |
|
|
| Report Abuse |
|
|
mew903
|
  |
| Joined: 03 Aug 2008 |
| Total Posts: 22071 |
|
|
| 01 Nov 2011 03:54 PM |
| pairs() returns everything in a table one at a time. |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 03:55 PM |
| @mew: No it doesn't. Trust me - I wrote the code at the top. |
|
|
| Report Abuse |
|
|
SDuke524
|
  |
| Joined: 29 Jul 2008 |
| Total Posts: 6267 |
|
|
| 01 Nov 2011 04:06 PM |
| NXTboy is correct, it returns next, array, nil. |
|
|
| Report Abuse |
|
|
mew903
|
  |
| Joined: 03 Aug 2008 |
| Total Posts: 22071 |
|
|
| 01 Nov 2011 04:06 PM |
idk :c
returns a number, then a value |
|
|
| Report Abuse |
|
|
mew903
|
  |
| Joined: 03 Aug 2008 |
| Total Posts: 22071 |
|
|
| 01 Nov 2011 04:07 PM |
| I don't use it that much :l |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 01 Nov 2011 04:20 PM |
You're muddling concepts:
local theNextFunction, theTable, aNil = pairs(t)
local number, value = pairs(t)() |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 02 Nov 2011 04:41 PM |
| Anyone think this is actually useful? Or is it pure evil? |
|
|
| Report Abuse |
|
|
XlegoX
|
  |
| Joined: 16 Jun 2008 |
| Total Posts: 14955 |
|
|
| 02 Nov 2011 05:17 PM |
Your implementation is really wasteful by the way, that's exactly the kind of case where you should be using the prototype pattern and creating one metatable and re-using it for all the instances.
There's actually a lot of libraries that do this sort of thing and declare a wrapper for arrays that adds their own library functionality. For instance, NumPy for Python works like this. |
|
|
| Report Abuse |
|
|
|
| 02 Nov 2011 05:21 PM |
"local number, value = pairs(t)()"
lua: test2.lua:2: bad argument #1 to '?' (table expected, got no value)
you're forgetting that the for loop calls next with the arguments of 't' and nil. |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 02 Nov 2011 05:24 PM |
I wasn't too sure where I should declare the metatable. This is presumably equivalently bad:
function array(t) local mt = { __call = function(self, _, key) return next(self, key) end } return setmetatable(t, mt) end
Do I need to go to this?
array = (function(mt) return function(t) return setmetatable(t, mt) end end)({ __call = function(self, _, key) return next(self, key) end }) |
|
|
| Report Abuse |
|
|
XlegoX
|
  |
| Joined: 16 Jun 2008 |
| Total Posts: 14955 |
|
|
| 02 Nov 2011 05:43 PM |
I mean:
do local MT = {...} function array(t) return setmetatable(t, MT) end end
So that you only ever construct one global metatable. |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 02 Nov 2011 06:04 PM |
| That behaves in the same way as my code. I'm not used to using `do end` to create a closure - javascript has taught be anonymous functions. |
|
|
| Report Abuse |
|
|
XlegoX
|
  |
| Joined: 16 Jun 2008 |
| Total Posts: 14955 |
|
|
| 03 Nov 2011 12:58 AM |
No, it actually doesn't. In fact, that highlights a key difference between JavaScript and Lua's virtual machines: the way they handle closure creation. Your version will create a new table, containing a new closure, every single time you call the "array" function. We can obviously agree that:
function() return {} end
Creates a new table every time it is executed. And your code is effectively a much more complicated version of this. At the very least you can agree it's creating a new table every time "array" is called.
Now, due to the way Lua closes over stuff, a new closure is also created every single time the function is called. Any time you write "function(...) ... end" in Lua a new closure is created every single time that line of code is passed. That's the opposite of JavaScript where closures are only created once within the scope of the enclosing function.
In JavaScript you would be right... but Lua isn't JavaScript. |
|
|
| Report Abuse |
|
|
NXTBoy
|
  |
| Joined: 25 Aug 2008 |
| Total Posts: 4533 |
|
|
| 03 Nov 2011 03:31 AM |
I don't believe it does create a new table every time it is called. Expanding it slightly by assigning the annonymous function to a variable:
local metatableMaker = function(mt) return function(t) return setmetatable(t, mt) end end
array = metatableMaker({ __call = function(self, _, key) return next(self, key) end })
I don't believe for a moment that that creates a new metatable every time. And the code I wrote above does the same thing, but uses an anonymous function instead of the named function `metatableMaker`. |
|
|
| Report Abuse |
|
|
XlegoX
|
  |
| Joined: 16 Jun 2008 |
| Total Posts: 14955 |
|
|
| 03 Nov 2011 07:24 AM |
I missed the last one of the three. The last one does actually work. The first two do not however. My argument does apply to the first two.
At the very least, the last way is not idiomatic Lua to do it that way. The whole reason that you do stuff in that sort way in JavaScript is because of the fact that closures are created. |
|
|
| Report Abuse |
|
|
Oysi
|
  |
| Joined: 06 Jul 2009 |
| Total Posts: 9058 |
|
| |
|
|
| 03 Nov 2011 06:01 PM |
for i, v in next, table, nil do -- note, the 3rd param (`nil`) is a starting place, it begins with nil, and continues with numbers print("enjoy your function calls when you could just do this instead"); end
|
|
|
| Report Abuse |
|
|
|
| 05 Nov 2011 12:57 PM |
Two above..i have another way of simplifying dat function array(r) local ms = { __call = function(self, _, key) return next(self, key) end } return setmetatable(t, ms) end
|
|
|
| Report Abuse |
|
|