This is my first quesion to this incredible community.
In these days I'm writing a Lua module for myself. Here it is a minimum part of the code with the problem
mt = {}
bf = {}
------------
-- bf.new --
------------
function bf.new(A)
local out = A
setmetatable(out,mt)
return out
end
-----------------
-- bf.tostring --
-----------------
function bf.tostring(A)
local typeA = type(A)
local out = ""
if typeA=="number" or typeA=="boolean" then
print(tostring(A))
elseif typeA=="table" then
local col = ""
local m = #A
local typeA1 = type(A[1])
for i=1,m do
if typeA1=="table" then
n = #A[1]
for j=1,n do
out = out.." "..tostring(A[i][j])
if j==n then
out = out.."\n"
end
end
elseif (typeA1=="number" or typeA1=="boolean") then
row = row.." "..tostring(A[i][j])
end
end
end
return out
end
-----------------------------
-- bf.compare(A,logical,B) --
-----------------------------
function bf.compare(A,logical,B)
if (logical~="<" and
logical~=">" and
logical~="<=" and
logical~=">=" and
logical~="==" and
logical~="~=") then
error("second input input must be a logical operator written into a string")
end
local out = {}
local ind = {}
local count = 0
if type(B)=="number" then
if type(A[1])=="table" then
for i=1,#A do
out[i] = {}
for j=1,#A[1] do
loadstring("cond ="..A[i][j]..logical..B)()
if cond then
out[i][j] = true
count = count+1
ind[count] = (i-1)*#A[1]+j
else
out[i][j] = false
end
end
end
elseif type(A[1])=="number" then
for j=1,#A do
loadstring("cond ="..A[j]..logical..B)()
if cond then
out[j] = true
count = count+1
ind[count] = j
else
out[j] = false
end
end
end
else
if (type(A[1])=="table" and type(B[1])=="table") then
if (#A==#B and #A[1]==#B[1]) then
for i=1,#A do
out[i] = {}
for j=1,#A[1] do
loadstring("cond ="..A[i][j]..logical..B[i][j])()
if cond then
out[i][j] = true
count = count+1
ind[count] = (i-1)*#A[1]+j
else
out[i][j] = false
end
end
end
else
error("The comparison can be done between "..
"two matrix with same dimension "..
"or between a matrix with a scalar value")
end
elseif (type(A[1])=="number" and type(B[1])=="number") then
if (#A==#B) then
for j=1,#A do
loadstring("cond ="..A[j]..logical..B[j])()
if cond then
out[j] = true
count = count+1
ind[count] = j
else
out[j] = false
end
end
else
error("Comparison between "..
"two vector with different dimension")
end
else
error("The comparison can be done between "..
"two matrix with same dimension "..
"or between a matrix with a scalar value")
end
end
return setmetatable(out,mt)--,ind
end
------------------------
-- metamethod setting --
------------------------
mt.__tostring = bf.tostring
mt.__lt = function(A,B) return bf.compare(A,"<",B) end
--------------------------
-- use of my metamethod --
--------------------------
A = bf.new{{1,2,3,4},{5,6,7,8},{9,10,11,12}}
B = bf.new{{3,6,1,8},{1,3,87,20},{11,2,5,7}}
C1 = bf.compare(A,"<",B)
C2 = A<B
print("What I want")
print(C1)
print("What I get")
print(C2)
If you run this little script, you can see that when I use the function bf.compare directly I have what I need. When I use the bf.compare through the metamethod, it gives me only a "scalar" value of true.
Any suggestion?
EDIT
Here it is the output:
What I want
true true false true
false false true true
true false false false
What I get
true
>Exit code: 0
A metatable is a regular Lua table containing a set of metamethods, which are associated with events in Lua. Events occur when Lua executes certain operations, like addition, string concatenation, comparisons etc. Metamethods are regular Lua functions which are called when a specific event occurs.
Metatables allow us to change the behavior of a table. For instance, using metatables, we can define how Lua computes the expression a+b , where a and b are tables. Whenever Lua tries to add two tables, it checks whether either of them has a metatable and whether that metatable has an __add field.
The use of the __index metamethod for inheritance is so common that Lua provides a shortcut. Despite the name, the __index metamethod does not need to be a function: It can be a table, instead. When it is a function, Lua calls it with the table and the absent key as its arguments.
The Lua manual states this pseudo code for the __lt metamethod
:
function lt_event (op1, op2)
if type(op1) == "number" and type(op2) == "number" then
return op1 < op2 -- numeric comparison
elseif type(op1) == "string" and type(op2) == "string" then
return op1 < op2 -- lexicographic comparison
else
local h = getbinhandler(op1, op2, "__lt")
if h then
return not not h(op1, op2)
else
error(···)
end
end
end
if there is a metamethod, then this line return not not h(op1, op2)
returns only a singel (the first) value returned by the handler h
, as not
is a unary operator. As a second effect it converts the handler output to a scalar: not {} == false
, and not false == true
.
Another small thing to notice: Lua tables are always passed by reference. Assigning a table to another variable just results in copying the pointer. Hence if you do stuff like:
function myFun(A)
local out=A
out[1]='bar'
return out
end
A={'foo',1,2,3}
B=myFun(A)
print(table.concat(B,', ')) -- OK
print(table.concat(A,', ')) -- A also changed, because:
print(A,B) -- they are the same table!
The result of all comparison metamethods is automatically cast to a boolean.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With