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