# Container objects

This chapter covers the standard container objects and more specifically, iterable objects such like `Cons`, `List` and `Vector`. Special objects like `Fifo`, `Queue` and `Bitset` are treated at the end of this chapter. Although the name container is sufficient enough to describe the object functionality, it is clear that a container is more than a simple object reservoir. In particular, the choice of a container object is often associated to the underlying algorithm used to store the object. For example, a vector is appropriate when storing by index is important. If the order of storage must be preserved, then a fifo object might be more appropriate. In any case, the choice of a container is always a question of compromise, so is the implementation.Container

## Cons object

Originally, a `Cons` object or cons cell have been the fundamental object of the Lisp or Scheme machine. The cons cell is the building block for list and is similar in some respect to the cons cell found in traditional functional programming language. A `Cons` object is a simple element used to build linked list. The cons cell holds an object and a pointer to the next cons cell. The cons cell object is called car and the next cons cell is called the cdr. This original Lisp notation is maintained here for the sake of tradition. Although a cons cell is the building block for single linked list, the cell itself is not a list object. When a list object is needed, the `List` double linked list object might be more appropriate. Cons car cdr

## Cons cell constructors

The default constructor creates a cons cell those car is initialized to the nil object. The constructor can also take one or several objects.

const nil-cons (Cons) const lst-cons (Cons 1 'a' "hello")

The constructor can take any kind of objects. When all objects have the same type, the result list is said to be homogeneous. If all objects do not have the same type, the result list is said to be heterogeneous. List can also be constructed directly by the parser. Since all internal forms are built with cons cell, the construction can be achieved by simply protecting the form from being interpreted.

const blist (protect ((1) ((2) ((3)))))

## Cons cell methods

A `Cons` object provides several methods to access the car and the cdr of a cons cell. Other methods allows access to a list by index.

const c (Cons "hello" "world") c:length # 2 c:get-car # "hello" c:get-cadr # "world" c:get 0 # "hello" c:get 1 # "world"

The `set-car` method set the car of the cons cell. The `add` method adds a new cons cell at the end of the cons list and set the car with the specified object.set-car add

## List object

The `List` object provides the facility of a double-link list. The `List` object is another example of iterable object. The `List` object provides support for forward and backward iteration. List

## List construction

A list is constructed like a cons cell with zero or more arguments. Unlike the cons cell, the `List` can have a null size.

const nil-list (List) const dbl-list (List 1 'a' "hello")

## List methods

The `List` object methods are similar the `Cons` object. The `add` method adds an object at the end of the list. The `insert` method inserts an object at the beginning of the list. add insert

const list (List "hello" "world") list:length # 2 list:get 0 # "hello" list:get 1 # "world" list:add "folks" # "hello" "world" "folks"

## Vector object

The `Vector` object provides the facility of an index array of objects. The `Vector` object is another example of iterable object. The `Vector` object provides support for forward and backward iteration. Vector

## Vector construction

A vector is constructed like a cons cell or a list. The default constructor creates a vector with 0 objects.

const nil-vector (Vector) const obj-vector (Vector 1 'a' "hello")

## Vector methods

The `Vector` object methods are similar to the `List` object. The `add` method appends an object at the end of the vector. The `set` method set a vector position by index. add set get

const vec (Vector "hello" "world") vec:length # 2 vec:get 0 # "hello" vec:get 1 # "world" vec:add "folks" # "hello" "world" "folks" vec:set 0 "bonjour" # "bonjour" "world" "folks"

## Set object

The `Set` object provides the facility of an object container. The `Set` object is another example of iterable object. The `Set` object provides support for forward iteration. One of the property of a set is that there is only one object representation per set. Adding two times the same object results in one object only. Set

## Set construction

A set is constructed like a vector. The default constructor creates a set with 0 objects.

const nil-set (Set) const obj-set (Set 1 'a' "hello")

## Set methods

The `Set` object methods are similar to the `Vector` object. The `add` method adds an object in the set. If the object is already in the set, the object is not added. The `length` method returns the number of elements in the set. length

const set (Set "hello" "world") set:get-size # 2 set:add "folks" # "hello" "world" "folks"

## Iteration

When an object is iterable, it can be used with the reserved keyword `for`. The `for` keyword iterates on one or several objects and binds associated symbols during each step of the iteration process. All iterable objects provides also the method `iterator` which returns an iterator for a given object. The use of iterator is justified during backward iteration, since `for` only perform forward iteration. iterable for iterator

## Function mapping

Given a function `func`, it is relatively easy to apply this function to all objects of an iterable object. The result is a list of successive calls with the function. Such function is called a mapping function and is generally called `map`.map

const map (obj func) { trans result (Cons) for (car) (obj) (result:link (func car)) eval result }

The `link` method differs from the `add` method in the sense that the object to append is set to the cons cell car if the car and cdr is nil.link

## Multiple iteration

Multiple iteration can be done with one call to `for`. The computation of a scalar product is a simple but illustrative example.

# compute the scalar product of two vectors const scalar-product (u v) { trans result 0 for (x y) (u v) (result:+= (* x y)) eval result }

Note that the function `scalar-product` does not make any assumption about the object to iterate. One could compute the scalar product between a vector a list for example. scalar-product

const u (Vector 1 2 3) const v (List 2 3 4) scalar-product u v

## Conversion of iterable objects

The use of an iterator is suitable for direct conversion between one object and another. The conversion to a vector can be simply defined as indicted below.

# convert an iterable object to a vector const to-vector (obj) { trans result (Vector) for (i) (obj) (result:add i) eval result }

## Explicit iterator

An explicit iterator is constructed with the `iterator` method. At construction, the iterator is reset to the beginning position. The `get-object` method returns the object at the current iterator position. The `next` advances the iterator to its next position. The `valid-p` method returns `true` if the iterator is in a valid position. When the iterator supports backward operations, the `prev` method move the iterator to the previous position. Note that `Cons` objects do not support backward iteration. The `begin` method reset the iterator to the beginning. The `end` method moves the iterator the last position. This method is available only with backward iterator.

# reverse a list const reverse-list (obj) { trans result (List) trans itlist (obj:iterator) itlist:end while (itlist:valid-p) { result:add (itlist:get-object)) itlist:prev } eval result }

## Special Objects

The engine incorporates other container objects. To name a few, such objects are the `Queue`, `Bitset` or `Fifo` objects.

## Queue object

A queue is a special object which acts as container with a fifo policy. When an object is placed in the queue, it remains there until it has been dequeued. The `Fifo` and `Queue` objects are somehow similar, with the fundamental difference that the queue is a blocking. Queue

# create a queue with objects const q (Queue 2) q:push "hello" q:push "world" q:empty-p # false q:length # 2 # dequeue some object q:pop # hello q:pop # world q:empty-p # true

## Bitset object

A bit set is a special container for bit. A bit set can be constructed with a specific size. When the bit set is constructed, each bit can be marked and tested by index. Initially, the bitset size is null. Bitset

# create a bit set by size const bs (Bitset 8) bitset-p bs # true # check, mark and clear assert false (bs:marked-p 0) bs:mark 0 assert true (bs:marked-p 0) bs:clear 0 assert false (bs:marked-p 0)