411 REFERENCE · Wikibooks
The Sway Reference Manual/Arrays and Lists
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
There are three main data structures built into Sway:
arrays, lists, and objects.
A data
structure is simply a collection of
bits of information
Bits in the informal sense, not zeros and ones.
that are
somehow glued together into a single whole. Each of these bits
can be be accessed individually. Usually, the bits are somehow
related, as well, so the data structure is a convenient way
to keep all these related bits nicely packaged together.
Arrays
An array is a data structure with the property that each
bit of information can be accessed just as quickly as the
others. To create an array, one uses the array function:
var a = array(42,64.0,"hello",:world);
This call creates an array that packages together four items or
elements. The variable a is created and set to point at
the package.
To access individual elements, one uses the 'square bracket'
notation or the 'dot' notation. For example, here's how to access the
first item in an array:
sway> a[0];
INTEGER: 42
sway> a . 0
INTEGER: 42
Note that array indexing (the number between the brackets or after
the dot is known as an index) is zero-based. That is, the first
element is at index 0, the second at index 1, and so on. Usually,
the 'dot notation' is not used for arrays, because of the high
precedence of 'dot'. For example:
a[row * cols + col]
is not the same as:
a . row * cols + col
as in the later, the element at the row index is retrieved and then
multiplied by cols and then that number is added to col.
To make the latter the same as the former, one would parenthesize the
index calculation:
a . (row * cols + col)
With bracket notation, the parenthesization is performed
automatically.
One can assign to arrays as well:
sway> a[0] = :forty-two;
SYMBOL: :forty-two
sway> a[0];
SYMBOL: :forty-two
One can also look at the tail end of an array. The tail end of
an array is the array without the first, or head, element.
sway> tail(a);
ARRAY: [64.000000000,"hello",:world]
sway> tail(a)[0];
REAL_NUMBER: 64.000000000
If you keep taking the tail of an array,
eventually you end up with :null:
sway>tail(tail(tail(tail(a))));
SYMBOL: :null;
Allocating empty arrays
It is possible to allocate an array without specifying the actual
elements:
var b = alloc(10);
This creates an array of ten elements (with indices ranging from
zero to nine).
sway> b[0];
SYMBOL: :null;
Each of the elements is initialized to :null.
Lists
A list is a data structure that has the property that
it can be lengthened and shortened by adding or removing
elements anywhere in the list. The trade-off for this
flexibility is that elements further down in the list
take longer to access than those elements earlier in
the list. Creating and accessing elements in a list is
very similar to arrays:
var a = list(42,64.0,"hello",:world);
sway> a[2];
STRING: "hello"
sway> a[3] = 13;
INTEGER: 13
To make a list longer, one can easily add an element to
the front of an existing list to make a new list:
var b = "apple" join a;
LIST: ("apple",42,64.000000000,"hello",:world)
Lists can share elements
It is very important to note that both a and b above share elements
and changes to a will affect b:
sway> a[1] = :pie;
SYMBOL: :pie
sway> a;
LIST: (42,:pie,"hello",:world);
sway> b;
LIST: ("apple",42,:pie,"hello",:world);
Making b independent of a is a task that seems easier than
it actually is. Here is a function that makes the attempt:
function join*(item,items)
{
function copy(stuff)
{
if (stuff == :null,:null,stuff[0] join copy(tail(stuff)));
}
item join copy(items);
}
This works in some cases:
var x = list(:apples,:pears,:bananas);
var y = :kumquats join* x; //note join*, not join
x[1] = :persimmons;
sway> x;
LIST: (:apples,:persimmons,:bananas);
sway> y;
LIST: (:kumquats,:apples,:pears,:bananas);
The problems is that the copy made by join* is a shallow
copy. That is, the incoming list was copied, but the elements
were not. In the case of a list of symbols, the elements do
not need to be copied, but that is not always the case:
var m = list(2,3,4);
sway> var p = list(1,m,5);
LIST: (1,(2,3,4),5)
sway> var q = 0 join* p; // note, join*, not join
LIST: (0,1,(2,3,4),5)
Got it so far? Not only does q share the elements of
p, they both share elements of m. Consider this move:
p[1][1] = 333;
where we change the first element of the first element of p:
sway> p;
LIST: (1,(2,333,4),5)
sway> q;
LIST: (0,1,(2,333,4),5)
A change made through p has still changed q. To solve this
problem, one needs to make a deep copy, where the elements
of the list are copied and the elements of the elements are
copied, and so on.
Changing the tail of a list
One can use the tail= function to change the tail of
a list:
var a = list(1,2,3);
a tail= list(222,333);
sway> a;
LIST: (1,222,333);
You can use tail= on any kind of list, even those produced by
tail:
var b = list(1,2,3);
tail(b) tail= list(333);
sway> b;
LIST: (1,2,333);
Inserting into the middle of a list
One uses a combination of join, tail, and tail= to insert into
the middle of a list. Here's how to insert an item after the
first element:
var c = list(1,3,4);
c tail= (3 join tail(c));
sway> c;
LIST: (1,2,3,4);
The parentheses are needed to insure that the tail of c is
not set to the number 3 and the result joined with the tail of c.
This method of insertion changes the original list. It is
also possible to make a new list with the inserted element
by writing an insertion function:
function insert(item,items,index)
{
if (index == 0)
{
item join items; //put the item at the head of the list
}
else
{
items[0] join insert(item,tail(items),index - 1);
}
}
var d = list(1,3,4);
var e = insert(2,d,1); //insert at the second element
sway> d;
LIST: (1,3,4);
sway> e;
LIST: (1,2,3,4);
Note that insert does a combination of a shallow copy of the
elements preceding the inserted element and creates a sharing
of the elements after the inserted element.
Objects
Objects are discussed in the next chapter.
Footnotes
Input and Output Objects