Containers are vars containing collections of values. Containers are used for
C++Script containers are C++ containers that are vars, and contain vars.
An array is a list of values, where each value can be referenced by a position. Use arrays
Arrays are created using the array() function to create an empty array:
var a = array();
Passing arguments to the array() function creates an array of with the given elements. E.g.
a = array(1,2,3);
The bracket operator appends items to an array:
var b = array(1)(2)(3);var c = array("this")("is")("an")("array");
What's happening here is that when you call an array var
as a functor, then that value is appended to the
array.
An array can be initialized to a given size with a single value, using fill_array() e.g.
var a = fill_array(20, ""); // An array of 20 empty strings
The array_from() function converts another container (such as a string or a list) into an array.
Items can be created, updated and retrieved from arrays using square-bracket notation.
var a = array();a[0] = "dog";a["1"] = "cat";a[2] = "mouse";writeln(a[1]); // Output: catwriteln(a.size()); // Output: 3
The size of the array does not need to be specified up front, since the array will automatically resize as items are added. If you set an item beyond the end of the array, then the intermediate values are set to null.
var a = array();a[100] = 12;writeln(a[10]); // nullwriteln(a.size()); // 101
If you retrieve an item that has not been assigned, or an item is retrieved
beyond the end of the array, then the null value is returned without
error.
The first item in the array has an index of 0. If the index is negative,
then the index is counted from the back (i.e. array[-1]
refers to the last item in the array).
The number of items in the array is retrieved using the size()
method. The empty() method returns
whether the array is empty. An array converts to true if it is non-empty.
if(a) writeln("a is non-empty");
When written as a string, the array displays the contents in square brackets.
writeln(a);
The front() and back() methods return the first and the last members of the array respectively. They are equivalent to a[0] and a[-1] respectively. If the array is empty, then front() and back() return null is returned without error.
Items can be added and removed from the end of the array, using the push_back() and pop_back() methods respectively. pop_back() returns the item that was removed, or null if the array is empty.
var a = array();a.push_back(10);a.push_back(9);a.push_back(8);writeln(a.pop_back()); // 8writeln(a.pop_back()); // 9writeln(a.pop_back()); // 10writeln(a.pop_back()); // null
The clear() method erases all items in the array. The erase() method erases a particular item, or a range of items.
var a = array('a','b','c','d','e','f');a.erase( range(1,3) );writeln(a); // [a,e,f]
Like all vars, the unary + operator clones the array. This performs a "shallow copy". The binary + operator appends two arrays, and the * operator repeats an array. The += operator appends one array to another, and the *= operators repeats the array a specified number of times. e.g.
var a = array(2)(3)(4);writeln( a+a ); // [2,3,4,2,3,4]writeln( a*3 ); // [2,3,4,2,3,4,2,3,4]
The var::insert() method can be used to insert an array of items into another array. The first argument to insert() is the position that the item is inserted, and the second argument is an item to be inserted.
A list (or linked list) stores a sequence of values. It is efficient to insert and delete items in the list, but it is not possible to look up an item at a particular index. This is the opposite of an array (where it is very fast to look up a particular item, and slow to insert or delete from anywhere other than the end). Lists are useful where
Lists can be created in the following ways:
var l1 = list(); // Empty listvar l3 = list(1)(2)(3)("horse");var l4 = list(1,2,3,"horse");var l5 = fill_list(10, "a") // The string "a" repeated 10 times
The size() method returns the number of items in the list, and the empty() method returns whether the list is empty (size() != 0). Converting to a bool (or var::as_bool()) returns true if the list is non-empty. Converted to a string, the list is written as a comma-separated list in square brackets.
assert( !l1 );writeln( items ); // [1,2,3,pony]assert( l2.size() == 4 );
The front() and back() methods return the first and last member in the list respectively. If the list is empty, then the methods return null but there is no error.
Lists do not have a [] operator to access individual members of the list.
The push_front() and push_back() methods add an item to either end of the list. The pop_front() and pop_back() methods remove an item from either end of the list, and return the removed value. If the list is empty, the pop_front() and pop_back() return null.
var l = list();l.push_back(1);l.push_back(2);l.push_back(3);writeln(l.front()); // 1writeln(l.pop_back()); // 3writeln(l); // [1,2]
The clear() method removes all items from the list.
The + operator joins two lists (the second operand can be any container),
and the * operator repeats the list the specified number of times. The +=
operator appends a container to the list, and the *= operator repeats the
list. e.g.
var l = list(1,2,3,4);writeln(l + array(5,6,7)); // [1,2,3,4,5,6,7]writeln(l * 2); // [1,2,3,4,1,2,3,4]l+=list('a'); // [1,2,3,4,a]l*=2; // [1,2,3,4,a,1,2,3,4,a]
A set is a list where each member is unique. Sets store their members in order. There is no numerical index, push_front(), push_back(), pop_front() or pop_back().
Sets are created using the functions set() and set_from(). The set() function creates an empty set, and arguments passed to the set() function create a set with the given members. The () operator inserts items into the set. set_from() converts another container into a set. e.g.
var s1 = set(); // Empty setvar s2 = set(3)(2)(1)(3); // Set of 1,2,3var s3 = set(3,2,1,3); // Set of 1,2,3
Like all containers, var::size() returns the number of items in the set. var::empty() returns true if the set is empty, and var::clear() removes all items from the set. Values are inserted into a set using var::insert(), and removed using var::erase(). The var::contains() method returns true if the set contains a particular item. e.g. (set.cpp)
#include <cppscript>var script_main(var){var s1 = set();s1.insert(1);s1.insert(2);s1.insert(3);writeln( s1.contains(2) ); // trues1.erase(2);writeln( s1.contains(2) ); // falsereturn 0;}
The set operator + performs the union of two sets, * the intersection, and - the set difference.
A map (called a dictionary in Python) associates two different values, called keys and values, where a value is stored with each key. Use maps when
Maps can compare any type of value provided that they are comparable. Note that integers always compare lower to doubles, which compare lower to strings etc.
Maps are created using the map() function.
var m = map();var m = map(1,"dog")(2,"cat");
The size() method returns the number of entries in the map, and the empty() method returns true if the map is empty. A map converted to a bool is true when the map is non-empty. The string form of a map lists the items in the map.
var m = map();assert( !m );
The square brackets operator is used to get and set items in the map. If you assign to an item in the map that doesn't exist, the item is created.
var pet_age = map();pet_age["sammy"] = 4;pet_age["necrox"] = 6.66;assert( pet_age["sammy"] == 4 );
The keys in a map can be iterated using foreach.
foreach( pet, pet_age )writeln( pet + " is " + pet_age[pet] );
The values can be iterated using the values() function to iterate values instead of keys:
foreach( age, pet_age.values() )writeln(age);
If you retrieve a non-existent item in a map, the result is null. Items can be erased from a map using the erase() method, and the presence of a key can be tested using the contains() method.
var m = map();assert( !m.contains(1) );m[1] = 12;assert( m.contains(1) );m.erase(1);assert( !m.contains(1) );
With the exception of strings (which are compared in lexographical order), containers are compared based only on whether they are the same object. The ordering of containers is consistent (fully ordered), so they can be used as keys in maps. The reason for this is because the comparison operator needs to be efficient and not go into an infinite loop.
The foreach macro repeats a block of code for each item in a container. Use foreach
The syntax is
foreach( v, container )body of loop
Where v is the loop variable, and container is the container to be iterated. The body of the loop is normally enclosed in curly brackets, which can be omitted if there is just a single statement in the loop. e.g.
foreach( i, array(1,2,3) )writeln(i);
Arrays, sets, lists and strings iterate through the values in the
container.
If you wish to iterate the keys (indexes) in the array, the keys() method retrieves the keys instead of the
values. The following are equivalent:
foreach( i, a ) writeln(i);foreach( i, a.keys() ) writeln(a[i]);
Maps and objects iterate through the keys of the container. e.g.
var m = map();m[1] = 2;m[2] = 3;foreach( i, m )writeln( "The value of " + i + " is " + m[i] );
The values of a map can be iterated directly using the values() method.
var m = map();m[1] = 2;m[2] = 3;foreach( i, m.values() )writeln( i ); // 2, 3
The C++ container methods (begin(),
end(), rbegin(), rend() etc) are also available.
Iterators are intended to be short-lived. Iterators cannot be stored as members of other
containers. If an iterator detects that its
underlying object has changed, then the iterator
throws the exception "expired_iterator".
A range is a special kind of container containing a linear sequence of numbers. The six functions to create ranges are:
See range1.cpp for an example.
The functions array_from(), list_from(), string_from() and set_from(), can be used to convert between containers of different types. e.g.
var items_array = array("1","2","3");var items_list = list_from(items_array);var items_string = string_from(items_list);
The transform() function transforms the values of the container. The transform() function doesn't create a copy or alter the original container. Use transform where
The transform function takes two arguments: the container to be transformed, and a functor which transforms each value. e.g.
var times_2(var a) { return a*2; }foreach( i, transform( range(1, 10), times_2 ) )writeln(i);
The filter() function creates a container from another container with certain values removed. The filter() function doesn't copy the values or alter the original container. Use filter() where you need to iterate over some (but not all) items in a container.
The filter() function takes two arguments: the container to be transformed, and a functor which returns true or false. e.g.
foreach( p, filter( range(2, 100), is_prime ) )writeln( p.as_string() + " is prime" );
The filtered result can be copied into another container as follows
var primes = array_from( filter( range(2, 100), is_prime ) );
A container can be iterated in reverse using the reverse() function. reverse() doesn't copy data, it merely causes the data to be iterated in reverse order.
foreach( i, reverse( array(1,2,3) ) )writeln(i);
The tail() function enumerates all items in a container except the first element. The tail() function doesn't copy the data or alter the original container. e.g.
foreach( i, tail(array(1,2,3)) )
writeln(i); // 2 3
tail() is not an efficient way to enumerate a list (i.e. avoid x=tail(x) in a loop).