Lua How iterators and for loops are work, what is it? - loops

How does it work and why does the loop return values for k, v vars in order?
Why if I just call the next() function many times it does not return the same result as in the loop?
Where does the for loop get the values for the second argument of the next() function?
I don't understand how it works
local t = {'a', 'b', 'c'}
-- prints 1 a, 2 b, 3 c
for k, v in next, t, nil do
print(k, v)
end
print()
print(next(t)) -- 1 a
print(next(t)) -- why not 2 b?
print(next(t)) -- why not 3 c?
I don't understand much there https://www.lua.org/pil/7.html, I asked a question. How it works in lua - iterators, for loops, closures

next is a stateless iterator. That is, next is a pure function - its return values are determined only by its inputs (the invariant state: the table & the loop control variable: the key)
This explains why
print(next(t)) -- 1 a
print(next(t)) -- why not 2 b?
print(next(t)) -- why not 3 c?
must print 1 a three times: Each time, you call next with the table as first (and nothing as second argument). If the second argument to next is nil or nothing, next returns the first key-value pair of the given table. To get the next k-v-pair, you need to pass that key to next: next(t, 1) may give you 2 b. To fix your subsequent calls to next, you need to always pass the last key to get the next k-v-pair:
local k, v = next(t)
print(k, v) -- 1st entry
k, v = next(t, k)
print(next(t, k)) -- 2nd entry
k, v = next(t, k)
print(next(t, k)) -- 3rd entry
note that it is not guaranteed that next traverses the list part of a table in order (although all implementations do it this way)
As outlined in the PIL chapter 7.2, a for-loop is just syntactic sugar to iterate over such an iterator (for the sake of simplicity, we assume every iterator returns two values like next):
for k, v in next, t, nil do
print(k, v)
end
is equivalent to
local iterator_func, invariant_state, control_var = next, t, nil
while true do
local k, v = iterator_func(invariant_state, control_var)
if k == nil then break end
print(k, v)
control_var = k
end
pairs(t) is just even more sugar for next, t, nil (which may also be written as next, t). You can trivially implement pairs yourself as function pairs() return next, t, nil end. ipairs works similarly, except it doesn't use next but an "inext" iterator which only considers integer keys (and guarantees inorder traversal).
Stateful iterators on the other hand usually have a hidden state (usually upvalues of a closure). Every call to the iterator function changes the hidden state; the invariant state and loop control variable usually is not needed at all (and ignored entirely). These iterators behave as you would expect. We can write a stateful pairs (that is, a pairs which always returns a closure remembering the current position of the "cursor" in the table) as follows by making the current key an upvalue:
function stateful_pairs(t)
local key
-- This is the iterator function: Note how we may take no params
-- since we have everything as an upvalue already
return function()
local value
key, value = next(t, key)
return key, value
end
end
this now works the way you expected in your example, because the closure returned by this pairs remembers its state in upvalues:
local stateful_next = stateful_pairs(t)
print(stateful_next(t)) -- 1 a
print(stateful_next(t)) -- 2 b
print(stateful_next(t)) -- 3 c
and you can still use this in a for-loop. For stateful iterators without parameters, a for loop is just syntactic sugar for calling a function until it returns nil:
for k, v in stateful_pairs(t) do
print(k, v)
end
Lua has a few stateful iterators such as io.lines or string.gmatch in its standard library; making them stateless would require a very ugly loop control variable & invariant state.

Related

Create Enumerable In Place Slice Of Array in Ruby

I'm looking to find a way to take an array in ruby, two indices in that array and return an enumerable object which will yield, in order, all the elements between and including the two indices. But for performance reasons, I want to do this subject to the following two conditions:
This slice to enum does not create a copy of the subarray I want a return an enum over. This rules out array[i..j].to_enum, for example because array[i..j] is creating a new array.
It's not necessary to loop over the entire array to create the enum.
I'm wondering if there's a way to do this using the standard library's enumerable or array functionality without having to explicitly create my own custom enumerator.
What I'm looking for is a cleaner way to create the below enumerator:
def enum_slice(array, i, j)
Enumerator.new do |y|
while i <= j
y << array[i] # this is confusing syntax for yield (see here: https://ruby-doc.org/core-2.6/Enumerator.html#method-c-new)
i += 1
end
end
end
That seems pretty reasonable, and could even be turned into an extension to Array itself:
module EnumSlice
def enum_slice(i, j)
Enumerator.new do |y|
while i <= j
y << self[i]
i += 1
end
end
end
end
Now within the Enumerator block, y represents a Proc you call when you have more data. If that block ends it's presumed you're done enumerating. There's no requirement to ever terminate, an infinite Enumerator is allowed, and in that case it's up to the caller to stop iterating.
So in other words, the y block argument can be called zero or more times, and each time it's called output is "emitted" from the enumerator. When that block exits the enumerator is considered done and is closed out, y is invalid at that point.
All y << x does is call the << method on Enumerator::Yielder, which is a bit of syntactical sugar to avoid having to do y.call(x) or y[x], both of which look kind of ugly.
Now you can add this to Array:
Array.include(EnumSlice)
Where now you can do stuff like this:
[ 1, 2, 3, 4, 5, 6 ].enum_slice(2, 4).each do |v|
p v
end
Giving you the correct output.
It's worth noting that despite having gone through all this work, this really doesn't save you any time. There's already built-in methods for this. Your enum_slice(a, i, j) method is equivalent to:
a.drop(i).take(j)
Is that close in terms of performance? A a quick benchmark can help test that theory:
require 'benchmark'
Benchmark.bm do |bm|
count = 10000
a = (0..100_000).to_a
bm.report(:enum_slice) do
count.times do
a.enum_slice(50_000, 25_000).each do
end
end
end
bm.report(:drop_take) do
count.times do
a.drop(50_000).take(25_000).each do
end
end
end
end
The results are:
user system total real
enum_slice 0.020536 0.000200 0.020736 ( 0.020751)
drop_take 7.682218 0.019815 7.702033 ( 7.720876)
So your approach is about 374x faster. Not bad!

Get disjoint elements from two tables

I am trying to get disjoint elements from two tables. My tables currently are defined as:
local t1={elem5=true, elem2=true, ...}
local t2={elem2=true, elem5=true, ...}
However it would not be much of a problem to change the structure to:
local t1={elem5, elem2, ...}
local t2={elem2, elem5, ...}
How could I get disjoint elements from both tables efficienlty? Also I need to know which table the elements where originally part of.
What first came to mind was to loop over both tables:
local fromt1={}
for k, v in pairs(t1) do
if not t2[k] then
fromt1[#fromt1+1]=v
end
end
local fromt2={}
for k, v in pairs(t2) do
if not t1[k] then
fromt2[#fromt2+1]=v
end
end
But these are two loops, so I looked some more and found a function for iterating two tables in one loop (link):
function pairs2(t, ...)
local i, a, k, v = 1, {...}
return
function()
repeat
k, v = next(t, k)
if k == nil then
i, t = i + 1, a[i]
end
until k ~= nil or not t
return k, v
end
end
local fromt1, fromt2={}, {}
for k, v in pairs2(t1, t2) do
if not t2[k] then
fromt1[#fromt1+1]=v
end
if not t1[k] then
fromt2[#fromt2+1]=v
end
end
Any more efficient/cleaner way to get disjoint elements from two tables in Lua?
There's nothing wrong with the first aproach.
1) You have to iterate over both tables one way or another; whether you do it in two loops or one is irrelevant.
2) You need at least two additional tables for the two result sets.
The one optimization you could do:
the # operator on tables is somewhat expensive, so you can sometimes improve perofmance by keeping a number variable and increasing it manually with each insertion. But please don't just implement this because I told you. Benchmark your code and only use this optimization if you find that your code actually runs faster.
EDIT: I just noticed that I kida skipped one possible implementation because I assumed you don't want to change either of the original tables. If however, one of the two is a throwaway table and you don't mind it changing, consider this:
local function remove_first_from_second(first, second)
for key in pairs(first) do
second[key] = nil
end
return second
end
Running this both ways won't work:
remove_first_from_second(fromt1, fromt2) -- Removes shared keys from fromt2
remove_first_from_second(fromt2, fromt1) -- Removes nothing from fromt1
Because at the time you call it the second time, fromt2 already contains only the keys that fromt1 doesn't have.
However, since this problem only affects the second call, you can get away with just one in-between table (assuming both original tables can be mutated)

Overriding assignment of value in Lua

I am using Lua v5.2.2 within a C application (embedded environment/MCU).
I need to expose some "parameters" in Lua, that for reading and writing you need to directly access the hardware (thus a C call is needed). I am looking however for other means to implement this than using plain old getters and setters.
I am mostly exploring the meta-programming power of Lua, but also I believe I can create a simpler interface for the user.
What I want to achieve is behaviour like the following:
my_param = createParameter{name="hw_param1", type="number", min=0, max=100}
my_param = 5
result = my_param + 3
On the first line a new parameter is created. This is a call towards a C function. Userdata is pushed to stack with a properly initialized struct. The hardware is also initialized as needed. A new table is returned.
On the second line an assignment is done to the parameter object. I want this to call a C function with a single argument (that of the assignment), so the value can be stored to the hardware registers.
On the third line the parameter is read. I again need a call towards a C function that will get the value of the parameter from the hardware registers, and that will return the result.
Note that the actual value of this parameter may change outside the scope of Lua, so reading the value once during initialization is not correct. The C function must be called each time to get the actual value. Similarly writing to the value must cause an immediate write to the hardware.
How can I accomplish this? Specifically can I alter the metatable of the parameter to achieve lines 2 and 3? (I am aware of how to implement line 1).
Also is it necessary to return a table from the constructor? May I, for example, return a primitive Lua type (e.g. a number) that will behave like above?
Yes, you can modify the metatable metamethods.
Line 2 would completely change the variable's value that it holds.
However, if you were to set a field in the parameter object like: my_param.x = n, the __newindex metamethod would get invoked; which you could overwrite the metamethod to behave as you would like. In your case you would make it set the parameter's field and update it with a C function call.
Regarding line 3, same principle applies, instead this time you would just use the __add metamethod, and manipulate the object when __add is invoked.
http://lua-users.org/wiki/MetamethodsTutorial
This isn't exactly what you're asking for, but it's close:
function createParameter(t)
param = {}
param.data = t
backingTable = {}
metatable = {}
function metatable.__index(t, k)
-- You can intercept the value here if you
-- want and pass it on to your C fuction.
return backingTable[k]
end
function metatable.__newindex(t, k, v)
-- You can intercept the value here if you
-- want and pass it on to your C fuction.
backingTable[k] = v
end
setmetatable(param, metatable)
return param
end
--------------------------------------------------------
my_param = createParameter{name="hw_param1", type="number", min=0, max=100}
my_param.value = 5
result = my_param.value + 3
print(result) -- prints 8
print(my_param.data.name) -- prints hw_param1
You might be able to do something tricky by assigning a metatable to the global table _G, but I think that would be kind of tricky to get set up right and could lead to unexpected outcomes.
Edit:
If you really hate having to have a level of indirection, and you really want to be able to set it directly, here's how you can do it by setting the global table.
globalMetatable = {}
globalParamNames = {}
globalParams = {}
function globalMetatable.__index(t, k)
if globalParamNames[k] then
-- You can intercept the value here if you
-- want and pass it on to your C fuction.
print("Read from param " .. k)
return globalParams[k]
else
rawget(_G, k)
end
end
function globalMetatable.__newindex(t, k, v)
if globalParamNames[k] then
-- You can intercept the value here if you
-- want and pass it on to your C fuction.
print("Wrote to param " .. k)
globalParams[k] = v
else
rawset(_G, k, v)
end
end
setmetatable(_G, globalMetatable)
function createParameter(t)
globalParamNames[t.varname] = true
end
--------------------------------------------------------
createParameter{varname="my_param", name="hw_param1", type="number", min=0, max=100}
my_param = 5
result = my_param + 3
print(result) -- prints 8
print(my_param) -- prints 5

Post-Condition Violation with Feature in Eiffel

This is part of the class. This class is called BAG[G -> {HASHABLE, COMPARABLE}]
it inherits from ADT_BAG which has deferred features such as count, extend, remove, remove_all, add_all... more, and domain to be re-implemented.
domain returns ARRAY[G] which is a sorted array list of G
i always get Post-condition violation "value_semantics" which is something to do with object comparison but I checked and there is no code for object comparison which is very weird.
I tried to remake the code for domain feature several times and it ALWAYS ends up with a post-condition violation or a fail.
When I check the debugger the array "a" that is returned from domain always has count 0 but this does not make sense because i move keys from table to "a" but count is still 0.
Maybe I am transferring the keys wrong to the array?
code:
count: INTEGER
-- cardinality of the domain
do
result := domain.count -- has to be domain.count because loop invariant: consistent: count = domain.count
end
domain: ARRAY[G]
-- sorted domain of bag
local
tmp: G
a: ARRAY[G]
do
create a.make_empty
across 1 |..| (a.count) as i -- MOVING keys from table to array
loop
across table as t
loop
if not a.has (t.key) then
a.enter (t.key, i.item)
i.forth
end
end
end
across 1 |..| (a.count-1) as i -- SORTING
loop
if a[i.item] > a[i.item+1] then
tmp := a[i.item]
a[i.item] := a[i.item+1]
a[i.item+1] := tmp
end
end
Result := a
ensure then
value_semantics: Result.object_comparison -- VIOLATION THROWN HERE
correct_items: across 1 |..| Result.count as j all
has(Result[j.item]) end
sorted: across 1 |..| (Result.count-1) as j all
Result[j.item] <= Result[j.item+1] end
end
test code:
t3: BOOLEAN
local
sorted_domain: ARRAY[STRING]
do
comment("t3:test sorted domain")
sorted_domain := <<"bolts", "hammers", "nuts">>
sorted_domain.compare_objects
Result := bag2.domain ~ sorted_domain -- fails here
check Result end
end
The first loop across 1 |..| (a.count) as i is not going to make a single iteration because a is empty (has no elements) at the beginning. Indeed, it has been just created with create a.make_empty.
Also, because keys in the table are unique it is useless to check whether a key has been added to the resulting array: the test not a.has (t.key) will always succeed.
Therefore the first loop should go over keys of a table and add them into the resulting array. The feature {ARRAY}.force may be of interest in this case. The addition of the new elements should not make any "holes" in the array though. One way to achieve this is to add a new element right after the current upper bound of the array.
The sorting loop is also incorrect. Here the situation is reversed compared to the previous one: sorting cannot be done in a single loop, at least two nested loops are required. The template seems to be using Insertion sort, its algorithm can be found elsewhere.
EDIT: the original answer referred to {ARRAY}.extend instead of {ARRAY}.force. Unfortunately {ARRAY}.extend is not generally available, but a.extend (x) would have the same effect as a.force (x, a.upper + 1).

Looking out of bounds in a 2D Lua table

I sometimes make small games in Lua, and often have to implement a 2D array as a grid or a board. When I want to check the cells surrounding a particular cell I usually give the 2D array a metatable so that when grid[outOfBoundsNum] is indexed it returns an empty table instead of an error:
setmetatable(grid, {
__index =
function(t, key)
if not table[key] then
return {}
else
return table[key]
end
end})
So when grid[outOfBoundsNum][anything] is called, it returns nil. Then, to check surrounding cells I do something like this :
for k, v in ipairs(neighbours) do
local cell = grid[v[1][v[2]]
if cell then -- check if this is actually within the 2D array
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end
end
This works, but it seems awkward to me. Is there a nicer or better way of doing it?
You don't need the metatable.
for k, v in ipairs(neighbours) do
local cell = grid[v[1]] and grid[v[1]][v[2]]
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end
end
Should do the job. It is a relatively common lua idiom to use logical and and or in expressions to act like the ternary operator in C.
So this line is equivalent to:
local cell = nil
if grid[v[1]]~=nil then
cell = grid[v[1]][v[2]]
end
You could write a forEachNeighbor() function which would take the grid, a position and a function and then call it with each existing neighborfield, i.e. encapsule the loop and the outer if in your second snippet in a function, you would use like:
forEachNeighbor(grid, position, function(cell)
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end)
Also, you could provide an at() function which would take a grid position as one parameter and return the corresponding field or nil, so that grid[v[1]][v[2]] becomes at(grid, v). This could also be implemented in addition to or instead of the __index metamethod.
For the __index metamethod itself: First, you probably meant t instead of table and rawget(t, key) instead of t[key] (which would cause infinite recursion).
But as lhf pointed out, the check is altogether unnecessary, because __index is only called when the key is not present in t. So you could just write:
__index = function(t, key)
return {}
end
One last remark:
I sometimes make small games in Lua, and often have to implement a 2D array
Why don't you implement it once and reuse it in other games? That's what modules are for!

Resources