I have a matrix class in C++ and the constructor is as follows:
template <typename T> CMatrix<T>::CMatrix(unsigned int varrow,unsigned int varcolumn)
{
//Lets set member variables
this->m_row=varrow;this->m_column=varcolumn;
//Create a place holder at heap
m_matrix=new T[varrow*varcolumn];
//
unsigned int i=0;
//
//Default matrix All elements are zero
for(i=0;i<varrow*varcolumn;i++)
{
m_matrix[i]=T();
}
//
}
I have implemented set and get methods as follows:
void SetCellValue(unsigned int row,unsigned int col,T value){ m_matrix[row*m_column+col]=value;}
T& GetCellValue(unsigned int row,unsigned int column) const{return m_matrix[row*m_column+column];}
The matrix class is accessible from Lua; however, the only way I can access to elements of matrix from Lua is, say if m is a matrix, m:GetValue or m:SetValue.
I want to know whether it is possible to access (set) matrix elements by a notation m[1,2] or maybe m(1,2) where m is a matrix, [1,2] is the element at first row and second column.
There are two basic issues. lua syntax, and lua semantics.
As far as syntax goes, m(1,2)
is definitely possible, if you use the __call
metamethod of the userdata.
I don't think that m[1,2]
is possible, I think that cannot be valid lua. You can use m[{1,2}]
if you use the __index
metamethod though.
The basic issue is that lua, like javascript, java, and other languages that are not C++, makes primitive integers be value types rather than reference types.
So you can easily make m(1,2)
return the correct integer, but if you want to write m(1,2) = 5
, that's harder, because m(1,2)
only returns a copy, not a reference.
In Java the (much maligned) solution is to use Boxing, where you wrap a primitive type in a class, in order to give it the correct (reference) semantics. The analogue here would be that you don't return an int, you return a userdata that wraps a reference to an int in your matrix.
In lua you usually avoid this by using the __index
and __newindex
metamethods. __index
is called when you request a child value from a userdata, and __newindex
is called when you assign a child value of a userdata. So no boxing is required, you can give it all whatever semantics you want.
The problem is that in this case, __index
and __newindex
will give you ugly syntax, you'll have to use m[{1,2}]
and m[{1,2}] = 5
to get it to work that way.
So, option (1) is, implement some kind of boxing for whatever type you have, and use the __call
metamethod.
Option (2) is, just use __index
and __newindex
and get used to writing m[{1,2}]
.
Option (3) is, try to use a different syntax m[1][2]
. Then you would want to make a new class that represents a row of the matrix, and make it be exposed to lua via m[1]
. However that also adds some complexity, there are various reasons you wouldn't want to do this. (And you indicated in comments that you don't really want to do this.)
The nicest thing would be if they extended the lua language so that m[1,2]
was just syntactic sugar for m[{1,2}]
or something like that. But, I wouldn't hold my breath.
If it were me, and option (3) is out of the question, I guess I would pick option (2) and get used to it. Would like to see if someone knows an improvement to it.