Container
From Axaptapedia
[edit] Containers
Description
Containers are a basic form of linked lists. Container functions that you might need are conins, conpoke, conpeek, condel and connull.
One use of containers is to pass multiple variables between objects using a single call. This is particularly useful when considering 3-tier performance, as each call across a tier can be quite expensive. In that case, putting your variables into one container and passing that in a single call will gain some performance.
Another use is to eliminate some tedious coding practices when writing display methods for report labels. If you have to return values from tables just use a container to store them all then conpeek them out using a global incremental pointer. This pointer can be reset in the executeSection of your Design then use the same method for the DataMethod of your report label something like
display real showValue() { pointer++; return any2real(conpeek(yourcontainer,pointer)); }
Declaration
To declare a container simply prefix the container name with keyword container.
static void Job33(Args _args) { container contest; ; }
Inserting data
I found two methods of inserting data into a container, one is using conins(container, start location, value1,...) same syntax can be used for conpoke(container, start location, value1,...). Using conpoke will actually modify data at that location as opposed to inserting, the idea is that initially you can build your container with conpoke but if your container will need data added then use conins which will insert the data at specified location and bump the rest of the data.
static void Job33(Args _args) { container contest; ; contest =conpoke(contest,1,"bla",3); //contest = conins(contest,1,"bla",3); print conpeek(contest,2); pause; }
In the above I use conpoke to insert two values starting at location 1 into contest. So after this our container will ... contain :) value "bla" at location 1 and value 3 at location 2. Data type for values is anytype. conpeeek returns anytype data type.
[edit] Performance considerations
One important detail about containers is the fact, that they are static structures. You cannot modify a container in-place, instead each addition or deletion has to iterate over the entire structure to copy all values into a newly allocated one. So every container manipulation has a runtime of O(n). Thus, whenever possible, read and write containers as a batch:
// writing a container packedClass = [ version, var1, var2, var3 ]; // reading a container [ version, var1, var2, var3 ] = packedClass;
I cannot tell how this is for reading operations, I suspect that they're O(1) much like arrays, but I wouldn't bet anything on it.
This whole thing is especially tricky in cases where you need variable-length containers which you usually create dynamically: This actually scales rather bad. However, there is a rather simple trick you can use if you run into this problem: The integrated List class does have a very nice packed format, which is just about what you need:
static container List2Container(List list) { container result; result = list.pack(); switch (conpeek(result, 1)) { case 1: return condel(result, 1, 3); default: throw error(strfmt("The List version %1 is not suppported.", conpeek(result, 1))); } }
I had performance problems in this respect with containers having 50+ elements which have to be assembled dynamically (for various reasons not important here). Changing to a list and converting it into a container in a single batch is at least one magnitude faster there (no wonder, as appending to a list works in O(1) rather then O(n)).
