As you have seen in my previous post, working with lists is easy if lists are build into a programming language. But what if the language itself is made of lists? The Lisp programming language is made of lists. Let’s have a look at what it’s like to work with lists in Lisp. I use the SBCL implementation of ANSI Common Lisp on openSUSE Linux for the examples.
You can create a list as follows.
CL-USER> (defparameter *mylist* (list ‘foo ‘bar ‘baz))
*MYLIST*
“CL-USER>” is the prompt of SBCL. The list is created with “(list )”. “*MYLIST*” is the return value of the call to “list”. You can ask for the length, access elements by index, lookup elements, ask for a subset, iterate over the list or change elements by index as follows.
CL-USER> (length *mylist*)
3
CL-USER> (nth 0 *mylist*)
FOO
CL-USER> (nth 2 *mylist*)
BAZ
CL-USER> (position ‘bar *mylist*)
1
CL-USER> (defparameter *sublist* (subseq *mylist* 0 2))
*SUBLIST*
CL-USER> (loop for i in *sublist* do (print i))
FOO
BAR
NIL
CL-USER> (setf (nth 1 *sublist*) ‘baz)
BAZ
CL-USER> (loop for i in *sublist* do (print i))
FOO
BAZ
NIL
Please note that the Lisp environment always gives a return value and returns “NIL” if there is nothing to return. A more Lisp-like version of the above would avoid creating global variables with “defparameter” and use “let” as follows.
(let ((mylist (list ‘foo ‘bar ‘baz)))
(print (length mylist))
(print (nth 0 mylist))
(print (nth 2 mylist))
(print (position ‘bar mylist))
(let ((sublist (subseq mylist 0 2)))
(loop for i
in sublist
do (print i))
(setf (nth 1 sublist) ‘baz)
(loop for i
in sublist
do (print i))))
Using lists in a language made of lists can be tricky but it’s worth to think about it for some time because this means that both, data and code are lists that can be manipulated in the same way.