[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Scheme simple data types ] | [ Up : Introduction to Scheme ] | [ Pairs > ] |
1.1.4 Scheme compound data types
There are also compound data types in Scheme. The types commonly used in LilyPond programming include pairs, lists, alists, and hash tables.
Pairs | ||
Lists | ||
Association lists (alists) | ||
Hash tables |
[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Scheme compound data types ] | [ Up : Scheme compound data types ] | [ Lists > ] |
Pairs
The foundational compound data type of Scheme is the pair
. As
might be expected from its name, a pair is two values glued together.
The operator used to form a pair is called cons
.
guile> (cons 4 5) (4 . 5) guile> |
Note that the pair is displayed as two items surrounded by
parentheses and separated by whitespace, a period (.
), and
more whitespace. The period is not a decimal point, but
rather an indicator of the pair.
Pairs can also be entered as literal values by preceding them with a single quote character.
guile> '(4 . 5) (4 . 5) guile> |
The two elements of a pair may be any valid Scheme value:
guile> (cons #t #f) (#t . #f) guile> '("blah-blah" . 3.1415926535) ("blah-blah" . 3.1415926535) guile> |
The first and second elements of the pair can be accessed by the
Scheme procedures car
and cdr
, respectively.
guile> (define mypair (cons 123 "hello there") … ) guile> (car mypair) 123 guile> (cdr mypair) "hello there" guile> |
Note: cdr
is pronounced "could-er", according Sussman and
Abelson, see
https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-14.html#footnote_Temp_133
[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Pairs ] | [ Up : Scheme compound data types ] | [ Association lists (alists) > ] |
Lists
A very common Scheme data structure is the list. Formally,
a ‘proper’ list is defined to be either the empty list with its
input form '()
and length 0, or a pair whose
cdr
in turn is a shorter list.
There are many ways of creating lists. Perhaps the most common is
with the list
procedure:
guile> (list 1 2 3 "abc" 17.5) (1 2 3 "abc" 17.5) |
Representing a list as individual elements separated by whitespace and enclosed in parentheses is actually a compacted rendition of the actual dotted pairs constituting the list, where the dot and an immediately following starting paren are removed along with the matching closing paren. Without this compaction, the output would have been
(1 . (2 . (3 . ("abc" . (17.5 . ()))))) |
As with the output, a list can also be entered (after adding a quote to avoid interpretation as a function call) as a literal list by enclosing its elements in parentheses:
guile> '(17 23 "foo" "bar" "bazzle") (17 23 "foo" "bar" "bazzle") |
Lists are a central part of Scheme. In, fact, Scheme is considered a dialect of lisp, where ‘lisp’ is an abbreviation for ‘List Processing’. Scheme expressions are all lists.
[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Lists ] | [ Up : Scheme compound data types ] | [ Hash tables > ] |
Association lists (alists)
A special type of list is an association list or alist. An alist is used to store data for easy retrieval.
Alists are lists whose elements are pairs. The car
of each
element is called the key, and the cdr
of each element
is called the value. The Scheme procedure assoc
is
used to retrieve an entry from the alist, and cdr
is used to
retrieve the value:
guile> (define my-alist '((1 . "A") (2 . "B") (3 . "C"))) guile> my-alist ((1 . "A") (2 . "B") (3 . "C")) guile> (assoc 2 my-alist) (2 . "B") guile> (cdr (assoc 2 my-alist)) "B" guile> |
Alists are widely used in LilyPond to store properties and other data.
[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Association lists (alists) ] | [ Up : Scheme compound data types ] | [ Calculations in Scheme > ] |
Hash tables
A data structure that is used occasionally in LilyPond. A hash table is similar to an array, but the indexes to the array can be any type of Scheme value, not just integers.
Hash tables are more efficient than alists if there is a lot of data to store and the data changes very infrequently.
The syntax to create hash tables is a bit complex, but you can see examples of it in the LilyPond source.
guile> (define h (make-hash-table 10)) guile> h #<hash-table 0/31> guile> (hashq-set! h 'key1 "val1") "val1" guile> (hashq-set! h 'key2 "val2") "val2" guile> (hashq-set! h 3 "val3") "val3" |
Values are retrieved from hash tables with hashq-ref
.
guile> (hashq-ref h 3) "val3" guile> (hashq-ref h 'key2) "val2" guile> |
Keys and values are retrieved as a pair with hashq-get-handle
.
This is a preferred way, because it will return #f
if a key is
not found.
guile> (hashq-get-handle h 'key1) (key1 . "val1") guile> (hashq-get-handle h 'frob) #f guile> |
[ << Scheme tutorial ] | [Top][Contents][Index] | [ Interfaces for programmers >> ] |
[ < Association lists (alists) ] | [ Up : Scheme compound data types ] | [ Calculations in Scheme > ] |