Lists

List Creation And Manipulation Using PicoLisp .

Drakopoulos Anastasios

Summary. This article describes list creation and manipulation using PicoLisp.

Introduction.
Besides symbols and numbers, lists are fundamental data structures for PicoLisp. In fact lists are of great importance for every Lisp dialect. In fact , your program in Lisp is a list as well as your functions. The interpreter awaits for a list which will be read and evaluated in order to produce results.

List Creation.
A list can be created using several methods. Each of them is described with examples.

Write the list.
A simple method to create a list is by writing data into parentheses. For example :
(11 22 33) → (11 22 33)
The interpreter returns this list. In case we want to save a list into a variable for further reference we could use “setq” function as in the next example:
(setq w (11 22 33))
Now if we provide the intepreter with the symbol “w” and press enter we get the list:
: w -> (11 22 33)

(quote a b c d) or '(a b c d).
Also we can use “quote” or the symbol “ ' ” in order to prevent evaluation producing a list. For example:
: (quote 1 2 3 4) -> (1 2 3 4)
: (setq q2 (quote 1 2 3 4)) -> (1 2 3 4)
: q2 -> (1 2 3 4)

(list args).
Another way of creating a list is by using the function “list”. Using this function we can create a list from the arguments provided.
(list 1 2 3 4) → (1 2 3 4)
We can save this using the following list:
(setq q1 (list 1 2 3 4))

(cons new-member a-list).
This function constructs a new list cell adding its first argument to the list given as its second argument. If we want to construct a list from the ground up, then we have to insert the new member to an empty list which is described by empty parentheses “()” or by the symbol “NIL”.
: (cons 1 ()) -> (1)
: (cons 'a ()) -> (a)
: (cons 1 NIL) -> (1)
: (cons 'a NIL) -> (a)
: (cons 'a) → (a)
: (cons 'a (11 22 33)) -> (a 11 22 33)

Where is my list ?
Every time we create a list it is returned and dies afterwards. If we want to use and reuse a list we have to create a variable which will keep our data, our list, for further reference. We have to use “setq” function. All we have to do is to create a list with three elements. The first element of the list will be the “setq” function. The second member of the list will be the name of the variable and the third ember of the list will be the content of the variable. The name of the variable is used for variable manipulation . If we want to create a list (1 2 3) and to save it into a variable with name “my-list” all we have to do is to write the following list:
(setq my-list (1 2 3))
Now if we write my-list and hit enter, the interpreter will return the content of the variable “my-list” which is (1 2 3). we van create lists with numbers, symbols, lists or lists of lists. Also we can have mixed lists. For example :
(list “hello” 11 22 33 “my friend” 'aSymbol)

List Manipulation.
PicoLisp provides many functions for list manipulation. We'll begin with “car” and “cdr”.

Return A Member Or A Sublist.
car & cdr.
The function “car” returns the first element of a list while the function “cdr” returns the rest of the list. For example:
: (car '("hello" 11 22 33 44)) -> "hello"
: (cdr '("hello" 11 22 33 44)) -> (11 22 33 44)
One could combine these two functions in order to get any member of the list according to the next examples:
(car a-list) → returns the first member of the list
(car(cdr a-list)) or (cadr a-list) → returns the second member of the list
(car(cdr(cdr a-list))) or (caddr a-list) → returns the third member of the list
(car(cdr(cdr(cdr a-list)))) or (cadddr a-list) → returns the fourth member of the list
(car(cdr(cdr(cdr(cdr a-list))))) or (caddddr a-list) → returns the fifth member of the list
This method with “car & cdr” and their combinations is rather old and primitive. The next section uses function “nth”.

(nth a-list an-index).
The function “nth” accepts a list as its first argument and an integer as its second argument and returns a sublist which begins from the position given by the integer. For example:
: (nth (11 22 33 44 55 66 77 88 99) 4) -> (44 55 66 77 88 99)
: (nth (11 22 33 44 55 66 77 88 99) 2) -> (22 33 44 55 66 77 88 99)
Using a combination of “car & nth” we can take any member of a given list.
(car(nth (11 22 33 44 55 66 77) 5)) → 55

(head a-num a-list).
Using the “head” function, one could take the first n elements of a list .
(head n a-list)
The “head” function takes as first argument the number of the first elements which will take and as second argument the list from which it will choose them. Finally “head' returns a new list. If we want to keep the returned list, we have to create a new variable using “setq”. For example:
(setq my-new-list (head 3 '(11 22 33 44 55 66 77 88 99)))
If we use as first argument a negative integer, then the “head” function counts backwards from the end of the list. Consider the difference in the following examples:
: (head -3 '(11 22 33 44 55 66 77 88 99)) -> (11 22 33 44 55 66)
: (head 3 '(11 22 33 44 55 66 77 88 99)) -> (11 22 33)

(tail a-num a-list).
We can use “tail” function in order to take the last n elements of a list. The function “tail” accepts two arguments. The first one is the number of members you wish to take and the second one is the list you want to use. For example:
: (tail 2 '(11 22 33 44 55 66 77 88 99)) -> (88 99)
Obviously you can provide a negative integer as the first argument which means that the “tail” function will start counting backwards beginning from the end of the list.
: (tail -1 '(11 22 33 44 55 66 77 88 99)) -> (22 33 44 55 66 77 88 99)
If you want to keep the returned list for further reference , you can create a new variable using the next list:
: (setq my-new-list (tail 2 '(11 22 33 44 55 66 77 88 99))) -> (88 99)
: my-new-list -> (88 99)

List Insertion.
In order to insert a new element at a position in a list we use the function “insert”. Its pattern follows:
(insert position list new-member)
The “insert” function accepts as its first argument the position at which the new member will be inserted. The list in which the insertion will take place is provided as second argument and the new member is given as third argument. Read the following examples:
: (insert 3 (11 22 33 44 55 66 77 88 99) 'hello) -> (11 22 hello 33 44 55 66 77 88 99)
: (insert 6 (11 22 33 44 55 66 77 88 99) "my friend") -> (11 22 33 44 55 "my friend" 66 77 88 99)

(append)
if you wish to append many lists you can use “append” function. This function accepts infinitely many lists as arguments. It returns a list appending all its arguments.

List Predicates.

List Check.
Using “lst?” we can check if the argument given to this function is a list. If the argument is a list “T” is returned. Otherwise NIL is returned. For example:
: (lst? 3) -> NIL #number
: (lst? ()) -> T #empty list
: (lst? (11 22 33)) -> T #list

Membership Check.
You can check if an element belongs to a list using the function “member”. The function “member” accepts two arguments. The first one is the element to be checked and the second one is the list in which we'll search in. The function “member” returns the sublist which begins with the element given, if it is a member of the list given as second argument. Otherwise NIL is returned. For example:
: (member 16 '(11 22 33 44 55 66 16 77 88 99)) -> (16 77 88 99)
If you wish to keep the returned result into a variable for further reference you can use “setq” as in the following list:
: (setq my-new-list (member 16 '(11 22 33 44 55 66 16 77 88 99))) -> (16 77 88 99)
: my-new-list -> (16 77 88 99)

Advanced Material.
This section includes advanced material concerning the previous sections.

List Creation by Repeating Values.
# creates a global list "a-list" repeating the same element many times
(de my-cons (a-mem a-times)
(setq a-list NIL)
(do a-times (setq a-list (cons a-mem a-list))))

#: (my-cons "google" 4) -> ("google" "google" "google" "google")
#: a-list -> ("google" "google" "google" "google")

Appending Repeated Values.
#appends the repeated values into an already existed list which is passed as argument
(de my-cons (a-mem a-times a-list)
(do a-times (setq a-list (cons a-mem a-list))) )

Returning A Local List.
# defines local list variable
(de list-member-times (a-mem a-times)
(let (a-list NIL)
(do a-times (setq a-list (cons a-mem a-list)))))
#{
: (list-member-times 'hello 4)
-> (hello hello hello hello)
: (list-member-times "hello" 4)
-> ("hello" "hello" "hello" "hello")
: (list-member-times '("hello") 4)
-> (("hello") ("hello") ("hello") ("hello")) }#

Successive cdrs Using Recursion.
# print successive cdrs
(de my-cdrs (a-list)
(if (<> a-list NIL)
(prog
(println (cdr a-list))
(my-cdrs (cdr a-list))) NIL))

First Through Fifth Element Using User Defined Functions.
car & cdr Method.
(de first (a-list) (car a-list))
(de second (a-list) (car(cdr a-list)))
(de third (a-list) (car(cdr(cdr a-list))))
(de fourth (a-list) (car(cdr(cdr(cdr a-list)))))
(de fifth (a-list) (car(cdr(cdr(cdr(cdr a-list))))))

car & nth Method.
(de third (a-list) (car(nth a-list 3)))
: (third (11 22 33333 44 55 66 77)) -> 33333

(de fourth (a-list) (car(nth a-list 4)))
: (fourth (11 22 33333 44 55 66 77)) -> 44

General nth-member Function.
(de nth-member (a-list a-num) (car(nth a-list a-num)))

#: (nth-member (11 22 33 44 55 66 77 88 99 100) 7) -> 77