$nav ===== Type: list ===== A list is a sequentially numbered collection of elements of other types. It's the closest thing LSL has to what other languages call an array. Lists can have any number of elements, from zero to as many as the available memory can hold. You can think of a list as a row of a spreadsheet in which each cell has an element that can be one of the LSL types, but instead of having the columns labelled "A", "B", and so on, they are numbered starting from zero. We refer to that numbering as the index or position of the element. List literals are written in LSL as a comma-separated sequence enclosed within brackets. An empty list has nothing within the brackets, so an empty list literal is written like this: ''[]'' Lists can not contain lists, but they can contain elements of any other type LSL supports. For example, ''[7, "yo!", <5, 1.4, -8>, PI]'' is a valid list literal. In it, the integer ''7'' is at position 0, the string ''"yo!"'' is at position 1, the vector ''<5, 1.4, -8>'' is at position 2, and the float ''PI'' (''3.1415927'') is at position 3. Or we can also say that the index of the element ''7'' is 0, and so on. Note that in LSL, there is no way to specify $lty[key] literals, therefore if a $ty[key] element is needed in a list, it has to come from a type cast, from a function, or from a variable of type $ty[key], and only the latter is allowed in the $globals section. See the $lty[key] type reference for details. Individual list elements are accessed through functions. The following functions can be used to access individual elements of a list: $lfn[llList2Integer], $lfn[llList2Float], $lfn[llList2String], $lfn[llList2Key], $lfn[llList2Vector], and $lfn[llList2Rot], depending on the type of the element we wish to extract. Each of them requires two arguments: the list to extract the element from, and the index of the element to extract. If the index is out of range, no error is reported; instead, a default value for the corresponding type is returned (zero for integers and floats, empty string for strings, empty or null key for keys, $lct[ZERO_VECTOR] for vectors, and $lct[ZERO_ROTATION] for rotations). See the reference of each function for details. The type of the list element we wish to extract may not match the type returned by the function we use. In some cases, LSL will convert the type for us; in others, a default value will be returned instead like for out-of-range indices. This table summarizes which elements can be extracted with which functions: ^Type of element in list^$lfn[llList2Integer]^$lfn[llList2Float]^$lfn[llList2String]^$lfn[llList2Key]^$lfn[llList2Vector]^$lfn[llList2Rot]^ ^$ty[integer]|**yes**|**yes**|**yes**|no|no|no| ^$ty[float]|**yes**|**yes**|**yes**|no|no|no| ^$ty[string]|**yes**|**yes**|**yes**|**yes**|no|no| ^$ty[key]|no|no|**yes**|**yes**|no|no| ^$ty[vector]|no|no|**yes**|no|**yes**|no| ^$ty[rotation]|no|no|**yes**|no|no|**yes**| Note in particular that a string element can't be extracted with $fn[llList2Vector] or $fn[llList2Rot], something that has bitten many scripters. Use ''(vector)llList2String(...)'' or ''(rotation)llList2String(...)'' instead. One quirk of LSL is that list variables can not be altered: in order to alter a list, you need to create a new list with the new contents. There are a number of functions to assist you with that, including $lfn[llListReplaceList], $lfn[llDeleteSubList], $lfn[llList2List] and so on. The types of the individual elements of a list can be found using $lfn[llGetListEntryType]. See $lfn[list/|list functions] for a complete reference. Type cast of any type other than list to list results in a list of one single element; for example, ''(list)3'' results in the same list as ''[3]'', and ''(list)"hi"'' results in the same list as ''["hi"]''. In $Mono, it is more efficient to use ''(list)element''; in $LSO it's also a bit more efficient, but it can also trigger a nasty bug with keys and strings; see $JIRA[SVC-1710]. Type cast of a list to list does nothing to it, e.g. ''(list)[5, 4]'' results in the same list as ''[5, 4]''. Type cast of a list to string results in a string that has every element of the list cast to string, and then all of them concatenated together, as if $lfn[llDumpList2String] was used with the list and an empty string as arguments; for example, ''(string)[3.7, 8.3]'' results in the string **3.7000008.300000**, which is the same result that would be obtained with ''llDumpList2String([3.7, 8.3], "")''. No other type casts are allowed for lists, e.g. ''(integer)list_var'' is not supported. === Joining lists === When used with lists, the $op[+] operator returns a new list which results from joining both lists (if one of the sides of the operator is not a list, it is converted to list first). For example, ''["a", "b"] + ["c", "d"]'' results in the same list as ''["a", "b", "c", "d"]''. Note that the element ''"c"'' is initially at position 0 of the second list, but in the final list it is at position 2. Another example: both ''[2] + 3'' and ''2 + [3]'' result in the same list as ''[2, 3]''. Note how, since one of the elements is of type list, the other is automatically cast to list before joining the lists. Note also that ''[2] + 3 + 4'' is //not// the same as ''[2] + (3 + 4)'': the former is evaluated left-to-right, so it first sees ''[2] + 3'' and results in ''[2, 3]'', then it sees ''[2, 3] + 4'' and results in ''[2, 3, 4]'', while the latter first evaluates the expression within parentheses, which does not contain lists and is consequently taken as integer addition, resulting in ''7'', then it sees ''[2] + 7'' and results in ''[2, 7]''. Similarly, the result of ''2 + 3 + [4]'' is equivalent to ''[5, 4]'' because the addition of ''2 + 3'' is performed first. **Advanced tips:** Internally, ''(list)element'' is more efficient than ''[element]''. Internally, if ''L'' is a list and ''e'' is of any type other than a list, ''L + e'' is more efficient than either ''L + [e]'' or ''L + (list)e''. That applies to code memory usage. However, when the element already exists in a list, it's more efficient, from the point of view of data memory usage, to append it using $lfn[llList2List]. See [[#Data memory usage]] below. === Comparing lists === The $op[!=] operator can be used on two lists. Counter-intuitively, the result is an integer that is //the subtraction of the lengths of the lists//. For example, ''[5] != [6, 2, "blah"]'' returns **-2**, because the length of the first list is 1 and the length of the second list is 3, and 1 - 3 equals -2. This quirk can be exploited to use $op[!=] as an alternative to $lfn[llGetListLength] to make the code take less space, but keep in mind that it is not portable to other grids. The $op[==] operator can also be used, and it compares the //lengths// of the lists. If the lengths are equal, it returns $lct[TRUE]; otherwise it returns $lct[FALSE]. For example, ''[5, 2] == ["hello", "world"]'' returns $ct[TRUE]. Both operators can be safely used to compare a list to the empty list. Note, however, that $op[!=] in particular may return values other than $ct[TRUE] and $ct[FALSE]. No other comparison operators are allowed. If you want to really compare whether two lists ''L1'' and ''L2'' are equal, you can use this trick: they are equal if ''L1 == L2 && llListFindList(L1, L2) == 0''. This works fine in $Mono, but it can give an erroneous result in $LSO if both lists are empty. For $LSO, you can use ''L1 == L2 && (llListFindList(L1, L2) == 0 || L1 == [])'' instead. ==== Examples ==== The following is a basic example that holds a list of all the people who touched it. If touched by the owner, it lists the people who have touched it so far. For simplicity, it has no clean-up or memory overflow guard, therefore it can result in a stack-heap collision error if many people touch it. list Touchers; default { touch_start(integer n) { if (llDetectedKey(0) == llGetOwner()) { integer length = llGetListLength(Touchers); integer index; // Loop through every index in the list and display the element for (index = 0; index < length; ++index) llOwnerSay(llList2String(Touchers, index)); } else { // Check if this name is already present in the list if (llListFindList(Touchers, (list)llDetectedName(0)) == -1) // Not present, add it. Touchers += llDetectedName(0); } } } ==== Data memory usage ==== This section is intended for advanced scripters. In $Mono, the size of list elements is evaluated as follows: ^ Type ^ Memory ^ | $ty[integer] | 16 | | $ty[float] | 16 | | $ty[string] | 18 + size of the string in UTF-16 (*) | | $ty[key] | 30 + size of the string in UTF-16 (*) | | $ty[vector] | 24 | | $ty[rotation] | 32 | (*) That's typically 2 bytes per character, but there are some special characters that take 4 bytes each, e.g. 𝔸 List elements can be reused. A reused element takes only 4 bytes regardless of the type. All elements can be reused by not extracting the elements from the list, but adding them to the list in list form. For example: list A = (list)1; A += llList2List(A, 0, 0); This list takes only 20 bytes (16 for the integer and 4 for a reference to the same integer). Strings in particular can also be reused if they already exist in a list, as long as they are not the result of some operation ($lfn[llList2String] is not considered an operation, but addition of strings and other functions such as $lfn[llToLower], $lfn[llGetSubString], etc. are). If they are the result of an operation, they are not reused, but they are reusable. For example: // This uses 20 bytes, per the table above: list A = (list)"X"; // This only adds 4 bytes to the list, because constant // strings are reused if they have been used // to assign them to some list element that // still contains the unmodified string, in this // case the first element of the list: A += "X"; // This adds 20 bytes to the list because the // string that results from a calculation is not // reused, even if it matches an existing // string: A = A + ("X" + ""); // However, it is reusable, so this element // will take 4 bytes only: A = A + llList2String(A, -1); string B = "Y"; // This adds 20 bytes to the list: A += B; // This adds 4 bytes to the list: A += B; Basically, the rule isn't whether the strings are equal, but whether they are handled verbatim without applying operations to them. The same trick fails with other types, including keys; adding e.g. a key variable to a list multiple times, results in one new instance of the key being counted for every addition. Same happens for integers, for example. But extracting them as lists still works. Lists are passed by reference to functions, meaning that when passing a list to a function, a new copy is not created, but instead the same list is used. === Limits === List size is only limited by available memory. However, list initializers (''['' ... '']'' literals used in global variables) and list constructors (''['' ... '']'' literals used in events or functions) have some limitations in $Mono: * List initializers are limited to 4096 elements. * List constructors are limited by an internal stack limit on expressions. The stack limit is 1024, but part of it is used internally and while doing operations, so you can't use a list constructor with more than 1022 elements and assign it to a variable. * This same stack limit affects any kind of expression, not just list constructors. It would be too hard to describe how the stack is used by expressions, but if you really have an expression that complex, you can work around the limit by breaking it up into several assignments.