Difference between revisions of "Category talk:LSL List"

From Second Life Wiki
Jump to navigation Jump to search
(On Concatenation)
Line 118: Line 118:


[[User:Cron Stardust|Cron Stardust]] 00:14, 31 December 2007 (PST)
[[User:Cron Stardust|Cron Stardust]] 00:14, 31 December 2007 (PST)
== Structures and Embedded lists ==
The proferred rule of not being able to embed a list, or a structure in a list as being impossible, or that we are left with a rather clunky strided list as a replacement couldn't be farther from the truth. I offer the following:
<pre>
list    OverLoaded = [];
integer  IntElement = 99;
string  StringElement = "You Can't Fool Me";
float    FloatElement = 3.1419;
key      KeyElement = NULL_KEY;
default
{
  state_entry()
  {
    Overloaded =[]
    + (string)IntElement
    + ","
    + StringElement
    + ","
    + (string)FloatElement
    + ","
    + (string)KeyElement;
  }
  touch_start( integer num )
  {
    ParseListElement( Overloaded, 0 );
  }
}
</pre>
Now what you have is a list with a single structured element.
<pre>
["99,You Can't Fool Me,3.1419,00000000-0000-0000-0000-000000000000"]
</pre>
Additional elements can be added to this list. Parsing, sorting, manipulating any portion of the structure is a simple matter of breaking it out. Once done, and upon manipulating any of the sub-elements, the uber-element needs to be manipulated with the available LSL functions in order to save it as sorted deleted or changed. I prefer this, however, to a thing I have seen fail, get scrambled, confused and just plain break. That being the strided list operations.
<pre>
ParseListElement( list superlist, integer element )
{
  list    Temp = llCSV2List( llList2String( superlist, element );
  integer IntPart = (integer)llList2String(Temp, 0 );
  string  StrPart = llList2String( Temp, 1 );
  float  FltPart = (float)llList2String( Temp, 3 );
  key    KeyPart = (key)llList2String( Temp, 4 );
}
</pre>
(please note the *lack* of giving into the temptation to use llList2<anything_but_string_here>. There are still a few bugs in those, and am not given to trust that they will work. *KNOWN* issues with llList2Key have lead me not to use any of the other variations, and directly typecast the result myself.)
While this is not as simple as saying
<pre>
struct MyStructure
{
  integer Int,
  string  Str,
  float  Flt,
  key    Key;
}
</pre>
it does accomplish the same thing. The only caveat is that if your string element actually contains commas you'd need to use llParseString2List with an appropriate seperator character rather than llCSV2List, but I have found that you can work around that by replacing actual commas in the strings with something else. Once again, sorting removing, replacing any single element of your structure involves the operation on the entire "super" list element, but is no more painful and far more trustworthy than a strided list. Not being one to leave things to chance, and knowing somewhat painfully and repeatedly that anything you haven't taken direct control over yourself is at the mercy, whims, and moods of LSL that day. A strided list is something which I have encountered as being subjectable to those far-flung LSL variations. This alternative measure will work... every time.

Revision as of 14:11, 2 February 2009

I want to document the fact that the following two expressions are NOT the same somehow.

[1] list_var += [(string)key_var]; [2] list_var += (string)key_var;

Why does this matter? why consider the following line of code:

index = llListFindList(list_var, [(string)key_var] );

If method [1] is used before the line above,you will find your value, however if you use method [2], you will not.


After much frustration I wanted to share this in hope someone else will not fall into the pit, or if it is a bug, it can be put in Jira. I'll let one of the Wiki gods decide what to do with this. --Awsoonn Rawley

I'll look into it, this sounds like a bug. Those two expressions should be equivalent. -- Strife Onizuka 18:26, 3 June 2007 (PDT)
I've done some testing and I cannot replicate your problem. Are you aware that indexing starts at zero and not one? -- Strife Onizuka 15:56, 5 June 2007 (PDT)
try this --Awsoonn Rawley 04:35, 6 June 2007 (PDT)
default
{
    state_entry()
    {
        list lst;
        key  uuid = llGetKey();
        
        lst = ["bob", "tom", "jerry"];
        
        lst += (string)uuid;
        
        llSay(0, (string)llListFindList(lst, [(string)uuid]) );
    }
}

I would really just like some documentation on this page about how to index into a list at all. Thanks - Kendown Baroque 00:48, 28 August 2007 (PDT)


On Concatenation

I have read in many places that there are two ways to concatenate lists, the "standard" way and a memory-saving "voodoo" technique. The standard way looks like this:

Code: "Standard" List Concatenation
list myList = ["element1"];
myList += ["element2"];

The "voodoo" technique looks like this:

Code: "Voodoo" List Concatenation
list myList = ["element1"];
myList = (myList=[]) + mylist + ["element2"];

So, being a bit of a computer scientist, I decided to give it a test. Here's my test code:

Code: Test Code - List Concat Standard
integer REPS = 30;

list myList;

integer i;

default { // INIT
    state_entry() {
        llOwnerSay("Testing memory usage...");
        
        myList = [];
        for (i = 0; i < REPS; ++i) {
            myList +=                       ["test3.0", "test3.1", "test3.2", "test3.3", "test3.4", "test3.5", "test3.6", "test3.7", "test3.8", "test3.9"];
        }
        llOwnerSay("List Standard Short Format Post-Concat 10*" + (string) REPS + " compound: " + (string) llGetFreeMemory());
        
        myList = [];
        for (i = 0; i < REPS; ++i) {
            myList =               ["test3.0", "test3.1", "test3.2", "test3.3", "test3.4", "test3.5", "test3.6", "test3.7", "test3.8", "test3.9"] + myList;
        }
        llOwnerSay("List Standard Long Format Pre-Concat 10*" + (string) REPS + " compound: " + (string) llGetFreeMemory());
    }
}

Output:

  • Testing memory usage...
  • List Standard Short Format Post-Concat 10*30 compound: 4261
  • List Standard Long Format Pre-Concat 10*30 compound: 4261
Code: Test Code - List Concat Voodoo
integer REPS = 30;

list myList;

integer i;

default { // INIT
    state_entry() {
        llOwnerSay("Testing memory usage...");
        
        myList = [];
        for (i = 0; i < REPS; ++i) {
            myList = (myList=[]) + myList + ["test4.0", "test4.1", "test4.2", "test4.3", "test4.4", "test4.5", "test4.6", "test4.7", "test4.8", "test4.9"];
        }
        llOwnerSay("List Voodoo Post-Concat 10*" + (string) REPS + " compound: " + (string) llGetFreeMemory());
        
        myList = [];
        for (i = 0; i < REPS; ++i) {
            myList = (myList=[]) + ["test4.0", "test4.1", "test4.2", "test4.3", "test4.4", "test4.5", "test4.6", "test4.7", "test4.8", "test4.9"] + myList;
        }
        llOwnerSay("List Voodoo Pre-Concat 10*" + (string) REPS + " compound: " + (string) llGetFreeMemory());
    }
}

Output:

  • Testing memory usage...
  • List Voodoo Post-Concat 10*30 compound: 9795
  • List Voodoo Pre-Concat 10*30 compound: 9739

Results

Interesting results... A gain of 5534 to 5478 bytes of memory for these tests.

Remember, bigger numbers mean more free memory, therefore less memory being used.

Cron Stardust 00:14, 31 December 2007 (PST)

Structures and Embedded lists

The proferred rule of not being able to embed a list, or a structure in a list as being impossible, or that we are left with a rather clunky strided list as a replacement couldn't be farther from the truth. I offer the following:


list     OverLoaded = [];
integer  IntElement = 99;
string   StringElement = "You Can't Fool Me";
float    FloatElement = 3.1419;
key      KeyElement = NULL_KEY;


default
{
  state_entry()
  {
    Overloaded =[] 
     + (string)IntElement 
     + "," 
     + StringElement 
     + "," 
     + (string)FloatElement 
     + "," 
     + (string)KeyElement;
  }
  touch_start( integer num )
  {
     ParseListElement( Overloaded, 0 );
  }
}

Now what you have is a list with a single structured element.

["99,You Can't Fool Me,3.1419,00000000-0000-0000-0000-000000000000"]

Additional elements can be added to this list. Parsing, sorting, manipulating any portion of the structure is a simple matter of breaking it out. Once done, and upon manipulating any of the sub-elements, the uber-element needs to be manipulated with the available LSL functions in order to save it as sorted deleted or changed. I prefer this, however, to a thing I have seen fail, get scrambled, confused and just plain break. That being the strided list operations.


ParseListElement( list superlist, integer element )
{
  list    Temp = llCSV2List( llList2String( superlist, element );
  integer IntPart = (integer)llList2String(Temp, 0 );
  string  StrPart = llList2String( Temp, 1 );
  float   FltPart = (float)llList2String( Temp, 3 );
  key     KeyPart = (key)llList2String( Temp, 4 );
}

(please note the *lack* of giving into the temptation to use llList2<anything_but_string_here>. There are still a few bugs in those, and am not given to trust that they will work. *KNOWN* issues with llList2Key have lead me not to use any of the other variations, and directly typecast the result myself.)

While this is not as simple as saying

struct MyStructure
 { 
  integer Int, 
  string  Str, 
  float   Flt, 
  key     Key;
 } 

it does accomplish the same thing. The only caveat is that if your string element actually contains commas you'd need to use llParseString2List with an appropriate seperator character rather than llCSV2List, but I have found that you can work around that by replacing actual commas in the strings with something else. Once again, sorting removing, replacing any single element of your structure involves the operation on the entire "super" list element, but is no more painful and far more trustworthy than a strided list. Not being one to leave things to chance, and knowing somewhat painfully and repeatedly that anything you haven't taken direct control over yourself is at the mercy, whims, and moods of LSL that day. A strided list is something which I have encountered as being subjectable to those far-flung LSL variations. This alternative measure will work... every time.