Lists and sequences

A sequence is a generalized array or list: Zero or more values treated as a compound value. Sequences have certain common operations, including indexing and iteration. (Technical note: Sequences generally implement the java.util.List interface, but Kawa will also treat strings and native Java arrays as sequences.)

Lists

In traditional Lisp-family languages, the list is the most important kind of sequence. (Don’t confuse Java’s List interface with Kawa’s use of the word list. They’re related, in that a Kawa “list” implements the List interface, so any list is also List, but not vice versa.)

A list is implemented as a chain of linked pairs. You can create a constant list by quoting a parenthesized list:

'(3 4 (10 20 30) "a string")

See Lists for details and operations.

Vectors

A vector is a sequence that is implemented by storing the elements side-by-side in memory. A vector uses less space than a list of the same length, and is generally more efficient than a list.

To create a vector you can use a bracketed list:

(! vec1 ['A 'B 'C 'D 'E 'F])

This creates a vector of 6 symbols and binds it to vec1. To select an element you can use the traditional vector-ref procedure:

(vector-ref vec1 3) ⇒ 'D

Alternatively, in Kawa you can use function-call notation:

(vec1 3) ⇒ 'D

You can also create a vector using the traditional vector constructor:

(! vec2 (vector 'A 'B 'C 'D 'E 'F))

There is one important difference between vec1 and vec2: You can modify vec2 by changing some or all of its elements. You can’t do that for vec1. (We say that vec1 is an immutable or constant vector, while vec1 is a mutable or modifiable vector.) To change an element use either the traditional vector-set! procedure, or function-call notation:

(vector-set! vec2 2 'Y)
(set! (vec2 4) 'Z)
vec2 ⇒ ['A 'B 'Y 'D 'Z 'F]
(vector-set! vec1 2 'Y) ⇒ throws exception

See Vectors for details and operations.

Java arrays and primitive vectors

See Using Java arrays for examples.

Indexing of general sequences

You can use function-call notation to index a generalized sequence, whether it is a list, vector, any java.util.List, native Java array, or string:

((list 'A 'B 'C 'D) 2)  ⇒ 'C
("abcdef" 3)  ⇒  ⇒
(! farr (float[] 1.5 3 4.5))  ;; native Java array
(farr 2) ⇒ 4.5

Note that indexing a list with an index i will be slow, since it has to step through the list i times. (So don’t do that!)

Ranges

A range is a sequence of numbers in order, spaced uniformly apart. Usually, these are (exact) integers that increase by one. The usual notation is:

[start <: end]

This is the sequence of integers starting with the integer start (inclusive) and ending with the integer end (exclusive). For example [3 <: 7] is the sequence [3 4 5 6].

The ‘<:’ is a keyword; the < is a mnemonic for the set of integers that are < the end value 6. You can also use <=: if you want to include the upper bound: [4 <=: 8] is [4 5 6 7 8].

You can use >=: or >: for a decreasing range. [5 >=: 1] or [5 >: 0] both evaluate to [5 4 3 2 1]. You can also specifify a step value: [1 by: 2 <=: 9], which evaluates to [1 3 5 7 9]. (Details here.)

Using vector and ranges indexes

If an index is a sequence of integers, the result is a new sequence (of the same type) selecting only the elements matching the index values. For example:

#|kawa:2|# (vec1 [3 5 2])
#(D F C)

In general, ((V1 V2) I) is (V1 (V2 I)).

You can use a range to create a slice - a contiguous subset of a list.

#|kawa:3|# (vec1 [2 <: 6])
#(C D E F)

A range is different from a vector integer in that you can use a range as the index in the LHS of a set!:

#|kawa:4|# (set! (vec1 [2 <: 4]) #(a b c d e))
#|kawa:5|# vec1
#(A B a b c d e E F)

Notice how the number of replaced elements can be different then the number of elements in the replacement value. I.e. you can do insertion and deletion this way.

#|kawa:7|# (! str1 (string-copy "ABCDEF"))
#|kawa:8|# (set! (str1 [2 <: 5]) "98")
AB98F