LISP
Basic
Syntax
LISP
programs are made up of three basic building blocks:
- Atom
- list
- string
An atom is
a number or string of contiguous characters. It includes numbers and
special characters.
Following
are examples of some valid atoms:
hello-from-GIMT
name
123008907
*hello*
Block#221
abc123
A list is
a sequence of atoms and/or other lists enclosed in parentheses.
Following are examples of some valid lists:
(
i am a list)
(a
(
a b c)
d e fgh)
(father
tom (
susan bill joe))
(sun
mon tue wed thur fri sat)
(
)
A string is
a group of characters enclosed in double quotation marks. Following
are examples of some valid strings:
"
I am a string"
"a
ba c d efg #$%^&!"
"Please
enter the following details :"
"Hello
from GIMT'! "
Adding
Comments
The
semicolon symbol (;) is used for indicating a comment line.
For
example
(write-line
"Hello
World")
;
greet the world
;
tell them your whereabouts
(write-line
"I
am at 'GIMT'! Learning LISP")
When
you execute the code, it returns the following result:
Hello
World
I
am at 'GIMT'!
Learning
LISP
Naming
Conventions in LISP
Name
or symbols can consist of any number of alphanumeric characters other
than whitespace, open and closing parentheses, double and single
quotes, backslash, comma, colon, semicolon and vertical bar. To use
these characters in a name, you need to use escape character (\).
A
name can have digits but not entirely made of digits, because then it
would be read as a number. Similarly a name can have periods, but
can't be made entirely of periods.
Use
of Single Quotation Mark
LISP
evaluates everything including the function arguments and list
members.
At
times, we need to take atoms or lists literally and don't want them
evaluated or treated as function calls.
To
do this, we need to precede the atom or the list with a single
quotation mark.
The
following example demonstrates this:
(write-line
"single
quote used, it inhibits evaluation")
(write
'(*
2 3))
(write-line
" ")
(write-line
"single quote not used, so expression evaluated")
(write
(* 2 3))
When
you execute the code, it returns the following result:
single
quote used,
it inhibits evaluation
(*
2
3)
single
quote not
used,
so expression evaluated
6
Data
Types
In
LISP, variables are not typed, but data objects are.
LISP
data types can be categorized as:
- Scalar types - for example, number types, characters, symbols etc.
- Data structures - for example, lists, vectors, bit-vectors, and strings.
Any
variable can take any LISP object as its value, unless you have
declared it explicitly.
Although,
it is not necessary to specify a data type for a LISP variable,
however, it helps in certain loop expansions, in method declarations
and some other situations
The
data types are arranged into a hierarchy. A data type is a set of
LISP objects and many objects may belong to one such set.
The typep predicate
is used for finding whether an object belongs to a specific type.
The type-of function
returns the data type of a given object.
Type
Specifiers in LISP
array | fixnum | package | simple-string |
atom | float | pathname | simple-vector |
bignum | function | random-state | single-float |
bit | hash-table | ratio | standard-char |
bit-vector | integer | rational | stream |
character | keyword | readtable | string |
[common] | list | sequence | [string-char] |
compiled-function | long-float | short-float | symbol |
complex | nill | signed-byte | t |
cons | null | simple-array | unsigned-byte |
double-float | number | simple-bit-vector | vector |
Example
1
(setq
x 10)
(setq
y 34.567)
(setq
ch nil)
(setq
n 123.78)
(setq
bg 11.0e+4)
(setq
r 124/2)
(print
x)
(print
y)
(print
n)
(print
ch)
(print
bg)
(print
r)
When
you execute the code, it returns the following result:
10
34.567
123.78
NIL
110000.0
62
Example
2
Next
let's check the types of the variables used in the previous example.
(setq
x 10)
(setq
y 34.567)
(setq
ch nil)
(setq
n 123.78)
(setq
bg 11.0e+4)
(setq
r 124/2)
(print
(type-of
x))
(print
(type-of
y))
(print
(type-of
n))
(print
(type-of
ch))
(print
(type-of
bg))
(print
(type-of
r))
When
you execute the code, it returns the following result:
(INTEGER
0
281474976710655)
SINGLE-FLOAT
SINGLE-FLOAT
NULL
SINGLE-FLOAT
(INTEGER
0
281474976710655)
Variables
Global
Variables
Global
variables have permanent values throughout the LISP system and remain
in effect until a new value is specified.
Global
variables are generally declared using the defvar construct.
For
example:
(defvar
x 234)
(write
x)
When
you execute the code, it returns the following result:
234
Since
there is no type declaration for variables in LISP, you directly
specify a value for a symbol with the setq construct
For
example,
(setq
x 10)
Example
setq
x 10)
(setq
y 20)
(format
t "x
= ~2d y = ~2d ~%"
x y)
(setq
x 100)
(setq
y 200)
(format
t "x
= ~2d y = ~2d"
x y)
When
you execute the code, it returns the following result:
x
=
10
y =
20
x
=
100
y =
200
Local
Variables
Local
variables are defined within a given procedure. The parameters named
as arguments within a function definition are also local variables.
Local variables are accessible only within the respective function.
Like
the global variables, local variables can also be created using
the setq construct.
There
are two other constructs -
let and prog for
creating local variables.
The let construct
has the following syntax:
(let
((var1
val1)
(var2
val2)..
(varn
valn))<s-expressions>)
Where
var1, var2, ..varn are variable names and val1, val2, .. valn are the
initial values assigned to the respective variables.
When let is
executed, each variable is assigned the respective value and lastly
the s-expression is
evaluated. The value of the last expression evaluated is returned.
If
you don't include an initial value for a variable, it is assigned
to nil.
Example
(let
((x
'a)
(y
'b)
(z
'c))
(format
t "x = ~a y = ~a z = ~a" x y z))
When
you execute the code, it returns the following result:
x
=
A y =
B z =
C
The prog construct
also has the list of local variables as its first argument, which is
followed by the body of the prog, and
any number of s-expressions.
The prog function
executes the list of s-expressions in sequence and returns nil unless
it encounters a function call named return. Then
the argument of the return function
is evaluated and returned.
Example
(prog
((x
'(a
b c))
(y
'(1
2
3))
(z
'(p
q 10)))
(format
t "x = ~a y = ~a z = ~a" x y z))
When
you execute the code, it returns the following result:
x
=
(A
B C)
y =
(1
2
3)
z =
(P
Q 10)
Constants
In
LISP, constants are variables that never change their values during
program execution. Constants are declared using
the defconstant construct.
Example
The
following example shows declaring a global constant PI and later
using this value inside a function named area-circle that
calculates the area of a circle.
The
defun construct is used for defining a function
(defconstant
PI 3.141592)
(defun
area-circle(rad)
(terpri)
(format
t "Radius:
~5f"
rad)
(format
t "~%Area:
~10f"
(*
PI rad rad)))
(area-circle
10)
When
you execute the code, it returns the following result:
Radius:
10.0
Area:
314.1592
Decision
Making
LISP
provides following types of decision making constructs.
Construct | Description |
cond | This construct is used for used for checking multiple test-action clauses.It can be compared to the nested if statements in other programming languages. |
if | The if construct has various forms. In simplest form it is followed by a test clause, a test action and some other consequent action(s). If the test clause evaluates to true, then the test action is executed otherwise, the consequent clause is evaluated. |
when | In simplest form it is followed by a test clause, and a test action. If the test clause evaluates to true, then the test action is executed otherwise, the consequent clause is evaluated. |
case | This construct implements multiple test-action clauses like the cond construct. However, it evaluates a key form and allows multiple action clauses based on the evaluation of that key form. |
The
cond Construct in LISP
Syntax
for cond is:
(cond
(test1
action1)
(test2
action2)
...
(testn
actionn))
Each
clause within the cond statement
consists of a conditional test and an action to be performed.
If
the first test following cond, test1,
is evaluated to be true, then the related action part, action1,
is executed, its value is returned and the rest of the clauses are
skipped over.
If
test1 evaluates
to be nil, then control moves to the second clause without executing
action1,
and the same process is followed.
If
none of the test conditions are evaluated to be true, then
the cond statement
returns nil.
Example
(setq
a 10)
(cond
((>
a 20)
(format
t "~%
a is less than 20"))
(t
(format
t "~%
value of a is ~d "
a)))
When
you execute the code, it returns the following result:
value
of a is
10
Please
note that the t in
the second clause ensures that the last action is performed if none
other would.
The
if Construct
The if macro
is followed by a test clause that evaluates to t or nil. If the test
clause is evaluated to the t, then the action following the test
clause is executed. If it is nil, then the next clause is evaluated.
Syntax
for if :
(if
(test-clause) (<action1)
(action2))
Example
1
(setq
a 10)
(if
(>
a 20)
(format
t "~%
a is less than 20"))
(format
t "~%
value of a is ~d "
a)
When
you execute the code, it returns the following result:
value
of a is
10
Example
2
The if clause
can be followed by an optional then clause:
(setq
a 10)
(if
(>
a 20)
then
(format
t "~%
a is less than 20"))
(format
t "~%
value of a is ~d "
a)
When
you execute the code, it returns the following result:
a
is
less than 20
value
of a is
10
Example
3
You
can also create an if-then-else type statement using the if clause.
(setq
a 100)
(if
(>
a 20)
(format
t "~%
a is greater than 20")
(format
t "~%
a is less than 20"))
(format
t "~%
value of a is ~d "
a)
When
you execute the code, it returns the following result:
a
is
greater than 20
value
of a is
100
The
when Construct
The when macro
is followed by a test clause that evaluates to t or nil. If the test
clause is evaluated to nil, then no form is evaluated and nil is
returned, however it the test result is t, then the action following
the test clause is executed.
Syntax
for when macro:
(when
(test-clause) (<action1)
)
Example
(setq
a 100)
(when
(>
a 20)
(format
t "~%
a is greater than 20"))
(format
t "~%
value of a is ~d "
a)
When
you execute the code, it returns the following result:
a
is
greater than 20
value
of a is
100
The case Construct
The case construct
implements multiple test-action clauses like the cond construct.
However, it evaluates a key form and allows multiple action clauses
based on the evaluation of that key form.
The
syntax for case macro is:
The
template for CASE is:
(case
(keyform)
((key1)
(action1
action2
...)
)
((key2)
(action1
action2
...)
)
...
((keyn)
(action1
action2
...)
))
Example
(setq
day 4)
(case
day
(1
(format
t "~%
Monday"))
(2
(format
t "~%
Tuesday"))
(3
(format
t "~%
Wednesday"))
(4
(format
t "~%
Thursday"))
(5
(format
t "~%
Friday"))
(6
(format
t "~%
Saturday"))
(7
(format
t "~%
Sunday")))
When
you execute the code, it returns the following result:
Thursday
Loops
LISP
provides the following types of constructs to handle looping
requirements. Click the following links to check their detail.
Construct | Description |
loop | The loop construct is the simplest form of iteration provided by LISP. In its simplest form It allows you to execute some statement(s) repeatedly until it finds a return statement. |
loop for | The loop for construct allows you to implement a for-loop like iteration as most common in other languages. |
do | The do construct is also used for performing iteration using LISP. It provides a structured form of iteration. |
dotimes | The dotimes construct allows looping for some fixed number of iterations. |
dolist | The dolist construct allows iteration through each element of a list. |
The
loop
Construct
Example
(setq
a 10)
(loop
(setq
a (+
a 1))
(write
a)
(terpri)
(when
(>
a 17)
(return
a)))
When
you execute the code, it returns the following result:
11
12
13
14
15
16
17
18
The loop
for Construct
The
for loop for construct follows several syntax:
(loop
for
loop-variable
in
<a
list>
do
(action))
(loop
for
loop-variable
from
value1 to value2
do
(action))
Example
1
(loop
for
x in
'(tom
dick harry)
do
(format t " ~s" x)
)
When
you execute the code, it returns the following result:
TOM
DICK HARRY
Example
2
(loop
for
a from
10
to 20
do
(print
a)
)
When
you execute the code, it returns the following result:
10
11
12
13
14
15
16
17
18
19
20
Example
3
(loop
for
x from
1
to 20
if(evenp
x)
do
(print
x)
)
When
you execute the code, it returns the following result:
2
4
6
8
10
12
14
16
18
20
The do Construct
The
syntax for do statement:
(do
(variable1
value1
updated-value1)
(variable2
value2
updated-value2)
(variable3
value3
updated-value3)
...
(test
return-value)
(s-expressions))
After
each iteration, the test is evaluated, and if it returns a non-nil or
true, the return-value is evaluated and returned.
The
last s-expression(s) is optional. If present, they are executed after
every iteration, until the test value returns true.
Example
(do
((x
0
(+
2
x))
(y
20
(
-
y 2)))
((=
x y)(-
x y))
(format
t "~%
x = ~d y = ~d"
x y))
When
you execute the code, it returns the following result:
x
=
0
y =
20
x
=
2
y =
18
x
=
4
y =
16
x
=
6
y =
14
x
=
8
y =
12
The dotimes Construct
Example
(dotimes
(n
11)
(print
n)
(prin1
(*
n n)))
When
you execute the code, it returns the following result:
0
0
1
1
2
4
3
9
4
16
5
25
6
36
7
49
8
64
9
81
10
100
The dolist Construct
Example
(dolist
(n
'(1
2 3 4 5 6 7 8 9))
(format
t "~% Number: ~d Square: ~d" n (* n n)))
When
you execute the code, it returns the following result:
Number:
1
Square:
1
Number:
2
Square:
4
Number:
3
Square:
9
Number:
4
Square:
16
Number:
5
Square:
25
Number:
6
Square:
36
Number:
7
Square:
49
Number:
8
Square:
64
Number:
9
Square:
81
Lists
Lists
are single linked lists. In LISP, lists are constructed as a chain of
a simple record structure named cons linked
together.
The
cons Record Structure
A cons is
a record structure containing two components called the car and
the cdr.
Cons
cells or cons are objects are pairs of values that are created using
the function cons.
The cons function
takes two arguments and returns a new cons cell containing the two
values. These values can be references to any kind of object.
If
the second value is not nil, or another cons cell, then the values
are printed as a dotted pair enclosed by parentheses.
The
two values in a cons cell are called the car and
the cdr.
The car function
is used to access the first value and the cdr function
is used to access the second value.
Example
(write
(cons
1
2))
(terpri)
(write
(cons
'a
'b))
(terpri)
(write
(cons
1
nil))
(terpri)
(write
(cons
1
(cons
2
nil)))
(terpri)
(write
(cons
1
(cons
2
(cons
3
nil))))
(terpri)
(write
(cons
'a
(cons 'b
(cons
'c
nil))))
(terpri)
(write
( car (cons 'a
(cons
'b
(cons 'c
nil)))))
(terpri)
(write
(
cdr (cons
'a
(cons 'b
(cons
'c
nil)))))
When
you execute the code, it returns the following result:
(1
.
2)
(A
.
B)
(1)
(1
2)
(1
2
3)
(A
B C)
A
(B
C)
Although
cons cells can be used to create lists, however, constructing a list
out of nested cons function
calls can't be the best solution. The list function
is rather used for creating lists in LISP.
The
list function can take any number of arguments and as it is a
function, it evaluates its arguments.
The first and rest functions
give the first element and the rest part of a list. The following
examples demonstrate the concepts.
Example
(write
(list
1
2))
(terpri)
(write
(list
'a
'b))
(terpri)
(write
(list
1
nil))
(terpri)
(write
(list
1
2
3))
(terpri)
(write
(list
'a
'b
'c))
(terpri)
(write
(list 3 4 'a
(car
'(b
. c)) (* 4 -2)))
(terpri)
(write
(list (list 'a
'b)
(list 'c
'd
'e)))
When
you execute the code, it returns the following result:
(1
2)
(A
B)
(1
NIL)
(1
2
3)
(A
B C)
(3
4
A B -8)
((A
B)
(C
D E))
List
Manipulating Functions
Function | Description |
car | It takes a list as argument, and returns its first element. |
cdr | It takes a list as argument, and returns a list without the first element. |
cons | It takes two arguments, an element and a list and returns a list with the element inserted at the first place. |
list | It takes any number of arguments and returns a list with the arguments as member elements of the list. |
append | It merges two or more list into one. |
last | It takes a list and returns a list containing the last element. |
member | It takes two arguments of which the second must be a list, if the first argument is a member of the second argument, and then it returns the remainder of the list beginning with the first argument. |
reverse | It takes a list and returns a list with the top elements in reverse order. |
Example
(write
(car
'(a
b c d e f)))
(terpri)
(write
(cdr '(a
b c d e f)))
(terpri)
(write
(cons
'a
'(b
c)))
(terpri)
(write
(list
'a
'(b
c)
'(e
f)))
(terpri)
(write
(append '(b
c)
'(e
f) '(p
q)
'()
'(g)))
(terpri)
(write
(last
'(a
b c d (e f))))
(terpri)
(write
(reverse '(a
b c d (e
f))))
When
you execute the code, it returns the following result:
A
(B
C D E F)
(A
B C)
(A
(B
C)
(E
F))
(B
C E F P Q G)
((E
F))
((E
F)
D C B A)
c programming sample codes
ReplyDeleteBlock if else statement