Lua / c++ problem handling named array entries - c++

I'm trying to write some c++ classes for interfacing with LUA and I am confused about the following:
In the following example: Wherigo.ZCommand returns a "Command" objects, also zcharacterFisherman.Commands is an array of Command objects:
With the following LUA code, I understand it and it works by properly (luaL_getn returns 3 in the zcharacterFisherman.Commands c++ set newindex function):
zcharacterFisherman.Commands = {
Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}
But when the array is defined with the following LUA code with a slightly different syntax luaL_getn returns 0.
zcharacterFisherman.Commands = {
Talk = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
Talk2 = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
Talk3 = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}
All objects are defined in c++ and the c++ objects hold all the object members so I am trying to just connect LUA to those c++ objects. Is this enough or do I need to post some of my code??

Lua is correct.
Your first example is forming a table that contains exactly three entries with indices 1, 2, and 3, none of which are specified explicitly. In this case table.maxn(), the # operator, and lua_objlen() all agree that there are three array elements.
Your second example is forming a table that contains exactly three entries with indices "Talk", "Talk2", and "Talk3", all specified explicitly but none are integers. In this case, table.maxn(), the # operator, and lua_objlen() all agree that there are zero array elements.
Why is this the right answer?
A Lua table is an associative array that can map values of any type (except nil) to values of any type (again, except nil). There is no other general container type in Lua, so tables are used for essentially everything. The implementation is not part of the Lua specification, but in practice a table is indexed as a hash table, and there is no natural ordering of the keys.
However, a common use case for tables is as a container that acts like a conventional array. Such a container has contiguous integer indices, and can be iterated in order. The table implementation makes this particularly efficient for integer keys starting at 1. These entries in the table are physically allocated as a contiguous array, and the keys are neither hashed nor stored. This saves storage space both in allocation overhead and by not storing some of the keys at all. It also saves run time since access is by direct calculation rather than by computing a hash and verifying the matching value.
Since arrays are just tables, the table initializer syntax has been designed to make that case easy and clear, as well as to support the other common use case where keys are strings that happen to be valid identifiers.
Lua 5.1 vs. Lua 5.0
In the current release of Lua (5.1.4, but this is true of all 5.1 releases) the Lua 5.0 functions table.getn(), table.setn(), luaL_getn(), and luaL_setn() are all deprecated, as is the common usage of a table field n for an array to indicate its array length. The table.getn() function is replaced by the # operator, and luaL_getn() by lua_objlen(). There is no equivalent to the setn() functions since Lua now manages the array size behind the scenes.
The # operator is defined on a table to return an integer such that indexing the table by the next larger integer returns nil. For an empty array (e.g. a = {}), it returns 0 because a[1] == nil. For a normal array, it returns the largest index in use. However, if an array has holes (missing elements) then it can return the index preceding any hole or the last index in use. If the actual largest integer index in use is required, the new function table.maxn() can be used, but it has to iterate over all table entries to find that maximum value and thus should only be used when using # can't.
This leads to a now common idiom for adding elements to an array: a[#a+1] = "some new value". This idiom is now often recommended in place of table.insert() for extending tables.

luaL_getn is for getting the highest numeric element of an array in Lua. An array is a table with only integer indices. When you define a table in Lua (the first example) without explicitly setting indices, you will get an array with elements 1, 2, and 3. Naturally, luaL_getn returns a 3 here. luaL_getn is NOT defined to return the number of elements in the table, it is defined to return the highest numeric index in the table (see http://www.lua.org/manual/5.1/manual.html#pdf-table.maxn)
The second example is NOT using numeric indices, and this table is not a Lua array -- it is more like a hash table. Since luaL_getn only works on true arrays, you wouldn't expect it to work here.
Unfortunately, there is no simple way to get the number of elements in a table (lua_objlen solves a related problem, but does not fix this one). The only way to do it is to either:
Always use array notation. Don't ever use anything else as the keys in your table. You will get a lot of speed-ups this way.
Iterate through your table and count the number of elements when you wish to know the table's size. The language does not provide a one-line method for getting the size of a full table, since general tables are implemented using hashes and do not track their element count.

Lua tables combine both hashtables and standard arrays.
Your first example is equivalent to:
zcharacterFisherman.Commands = {
[1] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
[2] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
[3] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}
getn helps you to find an empty numeric entry. If t[1]==nil then it is likely that table.getn(t) == 0. In your second example, you do not assign zcharacterFisherman.Commands[1], which is why you are getting 0.
zcharacterFisherman.Commands = {
[1] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
[2] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
[3] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}
zcharacterFisherman.Commands[1]=nil
print(table.getn(zcharacterFisherman.Commands))
This code will print 0 (or possibly a number >=3)
In general, there is no way to directly get the number of elements in the hashtable portion of the table without iterating over them (e.g. with pairs() )

Related

Efficient way to declare and access a huge array

I am writing a code for which I need to declare an array of around 200 indexes. Now to search a specific index I at least need to travel the array for a defined time or until desired value is achieved - hence at times I might need to travel 200 times if needed - for 200 value row.
This is exactly I wish to ignore so I landed coding it below way:
enum Index{ salary, age };
static const Datas Mydata [] =
{
[Index::one] = {"hello", function_call_ptr_1, function_call_ptr_2},
[Index::two] = "hekllo1", function_call_ptr_1, function_call_ptr_2}
};
Hence in my code I can directly seek it like below:
Mydata [Index::age]
Assuming that access to above structure is to be done inside a function - hence the function should receive Index value as argument to itself. But still what if arguments passed was wrong like:
age = 0;
fun(age);
Is there a better way to access Mydata so that its desired row can easily be accessed without any flaw?

Heterogeneous container of base class when the derived instances are not pointers

I have a base class and I want to store instances of its derivatives in a collection of some sort.
At first I created a map:
std::map<int, Variable> varriableItems;
and then ussing templates I created functions for each derivative and I tried passing in the derivatives like so:
template <>
void Array::addToMap<Number>(Number input)
{
numberVariables[itemCount_] = input;
itemCount_++;
}
By doing so this function was not called because everything was of type Variable of course and I found out about slicing.
So instead I changed my map to take in pointers to my base class
std::map<int, Variable*> varriableItems;
but the problem I have is that all my objects are not created as pointers so I could not pass them in and I was getting errors.
No suitable conversion from "Number" to "Variable" exists.
Due to my implementation I can only create instances of objects
like so:
auto aNumberVariable = Number{50};
Ofcourse if I instead do:
Number aNumberVariable = new Number(50);
it works great.
The reason am doing this is explained bellow.
Please bear with me because this is a weird assignment.
We were asked to create a program that behaves/understands the syntax of a programming language called Logo, without actually analyzing the text as an input file, but rather "disguise" it to appear as such while in fact we just use C++ using what we learned from C++ and lots of overloads and pre-processor tricks
We have to be able to make our own "types" of variables called NUMBER,WORD,BOOLEAN,ARRAY, LIST,SENTENCE.
To declare them we have to use(note no semi-colons should be used):
//define number variable with value 21
MAKE number = NUMBER: 21
//define hello variable with value “hello”
MAKE hello = WORD: “hello”
//define myMoves variable contains list of turtle moves
MAKE myMoves = LIST [
LIST [WORD: “FORWARD”, NUMBER: 100],
LIST [WORD: “LEFT”, NUMBER: 90],
LIST [WORD: “FORWARD”, NUMBER: 100]
]
//define array variable with empty array
MAKE array = ARRAY {
number,
hello,
NUMBER: 12
BOOLEAN: TRUE,
ARRAY {
myMoves,
LIST [WORD: “BACK”, NUMBER: 100]
}
}
//define book variable with sentence type
MAKE book = SENTENCE (hello, WORD: “hello!”)
That's just a small part, we later have to support functions, nested loops , etc.
So do this I have to find a way to use the colon since I cannot overload it, so I did this:
//Create an instance of Number and write the first half of the ternary operator so we
//always get the false value so we can use the : like this
#define NUMBER Number{} = (false) ? 0
//semicolon infront for the previous command that needs it
#define MAKE ;auto
So now this:
//following commands will deal with the semicolon
MAKE myNumber = NUMBER: 21
worked great and it actually gets replaced by the processor to this:
auto myNumber = Number{} = (false) ? 0 : 21
So i worked with this for all my derivatives and I proceeded to overload operators to compare them, implement if else function in a similarly weird syntax.
Now I either have to figure out a way to make this work again but this time creating them as pointer instead (Which I assume is the only way for this to work, but I so far I couldn't figure it out) or create a single class for all types but doing it in separate objects that all inherit from a single base class makes more sense to me.
And am not sure how strict they will be, it is an unconventional project assignment for sure.
The reason I want to hold them together in a container is so I can then implement an Array and list object that can hold every type. At first I tried to use a different container for each type and made an iterator to iterate multiple maps separately, but when I got to the LIST implementation things got weird.
The list syntax is using the brackets [ ] which can only get 1 input value, so the idea was to collect them by overloading the comma operator and pass in one value to the list object.
I know this is weird , thank you for your time
I didn't read through all of your post. (actually I did because your task is so ... beyond words) but if you need polymorphism in a container and you also need the container to hold the objects, then the solution is unique_ptr:
container<std::unique_ptr<Base>>
In your case it would go something along this:
std::unordered_map<int, std::unique_ptr<Variable>> varriableItems;
varriableItems[0] = std::make_unique<Number>(50);

Hashing with separate chaining

Let's consider that for two different inputs("tomas", "peter") a hash function yields the same key (3).
Please correct my assumtion how it works under the hood with the separate chaining:
In a hash table, index 3 contains a pointer to a linked list header. The list contains two nodes implemented for example like this:
struct node{
char value_name[];
int value;
node* ptr_to_next_node;
};
The searching mechanism remembers the input name ("peter") and compares value_name in nodes. When it equals with "peter", the mechanism would return the value.
Is this correct? I've learned that ordinary linked list doesn't contain the name of the node so that I didn't know, how could I find the correspondind value in the list with nodes like this for different names ("tomas", "peter"):
struct node{
int value;
node* ptr_to_next_node;
};
Yes, its correct that this is a possible implementation of part of a hash table.
When you say an "ordinary linked list doesn't contain the name of the node", I'd be expecting a linked list to be generic if the implementation language allows that. In C++ it would be a template.
It would be a linked list of a certain type and each element would have an instance of or a handle to that type and a pointer to the next element as your second code snippet shows except substituting int with the type.
In this case the type would most likely be a key-value-pair
So the linked list in that case doesn't directly contain the name - it contains an object that contains the name (and the value)
This is just a possible implementation though. There are other options
Yes, basically: a table of structures, with the hash function limited to return a value between 0 and table size - 1, and that is used as an index into the table.
This gets you to the top of the list of chained elements, which will be greater than or equal to zero in number.
To save time and space, usually the table element is itself a chain list element. Since you specified strings as the data being stored in the hash table, usually the structure would be more like:
struct hash_table_element {
unsigned int length;
char *data_string;
struct hash_table_element *next;
}
and the string space allocated dynamically, maybe with one of the standard library functions. There are a number of ways to manage string tables that may optimize your particular use case, of course, and checking the length first can often times speed up the search if you use short cut evaluation:
if (length == element->length &&
memcmp(string, element->data_string, length))
{
found = TRUE
};
This will not waste time comparing the strings unless they are the same length.

Alternative to nested maps in standard namespace

I have nested map of type:
std::map<int,std::map<pointer,pointer>>
I am iterating over the map each time/per frame and doing updates on it.So basically I have 2 nested if loops.
i have an array and i need to sort the data with 2 attributes. First attribute is integer which is the first key, then second attribute is a pointer which is a key of nested map inside the main map. so my code is something like:
iterator = outermap.find();
if(iterator!=outermap.end()){
value = iterator->second;
it1 = value.find();
if(it1!=value.end(){
value1 = it1->second;
// do something
}
else{
// do something and add new value
}
}
else {
// do something and add the values
}
This is really slow and causing my application to drop frame rate. Is there any alternative to this? Can we use hash codes and linked list to achieve the same?
You can use std::unordered_map, it will hash the keys so finds complete faster. Using value = iterator->second is copying your entire map to the 'value' variable. Using a reference avoids unnecessary copying and is better for performance, eg: auto & value = iterator->second.
Also std::map is guaranteed to be ordered. This can be used to your advantage since your keys are integers for the outermost map.
Firstly, your question is a bit vague, so this may or may not fit your problem.
Now, you have a map<int, map<pointer, pointer>>, but you never operate on the inner map itself. All you do is look up a value by an int and a pointer. This is also exactly what you should do instead, use an aggregate of those two as key in a map. The type for that is pair<int, pointer>, the map then becomes a map<pair<int, pointer>, pointer>.
One more note: You seem to know the keys to search in the map in advance. If the check whether the element exists is not just for safety, you could also use the overloaded operator[] of the map. The lookup then becomes outermap[ikey][pkey] and returns a default-initialized pointer (so probably a null pointer, it pointer really is a pointer). For the suggested combined map, the lookup would be outermap[make_pair(ikey, pkey)].

How to make a variable name without creating an array in C++?

How do you make a variable name where you create a variable and then in brackets the variable number? (By the way, I'm just guessing out how the code should be so that you get what I'm trying to say.) For example:
int var[5];
//create a variable var[5], but not var[4], var[3], var[2], etc.
Then, the variable number must be able to be accessed by a variable value:
int number = 5;
int var[number]; //creates a var[5], not a var[4], etc.
int var[2]; //creates a var[2], not a var[1], etc.
cout >>var[number];
number = 2;
cin << var[number];
If I'm way off track with my "example", please suggest something else. I need something similar to this for my game to operate, because I must be able to create an unlimited instance of bullets, but they will also be destroyed at one point.
It looks like you are looking for the functionality provided by std::map which is a container used to map keys to values.
Documentation of std::map
Example use
In the below example we bind the value 123 to the integer key 4, and the value 321 to key 8. We then use a std::map<int,int>::const_iterator to iterate over the key/value pairs in our std::map named m.
#include <map>
...
std::map<int, int> m;
m[4] = 123;
m[8] = 321;
for (std::map<int, int>::const_iterator cit = m.begin (); cit != m.end (); ++cit)
std::cout << cit->first << " -> " << cit->second << std::endl;
output:
4 -> 123
8 -> 321
It looks like you want variable length arrays, which is not something C++ supports. In most cases, the correct solution is to use an std::vector instead, as in
int number = 42; // or whatever
std::vector<int> var(number);
You can use std::vector as you would use an array in most cases, and you gain a lot of bonus functionality.
If I understand what you want correctly (which I'm not certain that I do), you want to be able to create a place to hold objects and use them according to some index number, but to only create the specific objects which go in it on demand. You want do to this either because 1) you don't know how many objects you're going to create or 2) you aren't going to use every index number or 3) both.
If (1) then you should probably just use a vector, which is an array-like structure which grows automatically as you add more things to it. Look up std::vector.
If (2) then you could use an array of pointers and initially set all of the values to null and then use new to create the objects as needed. (Or you could use the solution recommend in part 3.)
If (3) then you want to use some form of map or hash table. These structures will let you find things by number even when not all numbers are in use and will grow as needed. I would highly recommend a hash table, but in C++, there isn't one in the STL, so you have to build your own or find one in a third-party library. For ease, you can use std::map, which is part of the STL. It does basically the same thing, but is slower. Some C++ distributions also include std::hash_map. If it's available, that should be used instead because it will be faster than std::map.