Here's a sample gcl session:
{exposition} 2> gcl
GCL (GNU Common Lisp) Version(2.3) Mon Mar 13 14:49:55 PST 2000
Licensed under GNU Library General Public License
Contains Enhancements by W. Schelter
>(+ 1 2)
3
>
>(- 2 1) 1 >(+ 1 0) 1 >(* 2 8) 16 >(/ 4 2) 2 >(+ 3 (- 10 6)) Nested expression 7 >(* 4 2.0) Notice that we can force the result type to real 8.0
>'a A >'C C >'LONG_symbol-foo LONG_SYMBOL-FOO
>'(1 2 3) (1 2 3) >'(+ 1 1) (+ 1 1) >'((a b) (c d)) ((A B) (C D))
>nil NIL >'() NIL
>(not nil) T >(or t) T >(or t nil) T >(and t nil) NIL >(not (and t nil)) T
>(= 1 1) T >(= 3 4) NIL >(equal '(1 3) '(1 3)) T >(equal 'a 'a) T >(equal 'a 'b) NIL >(equal 'a 'a 'a) T >(= 1 1 1) T
cond takes a variable number of arguments. Each argument has two parts, a condition and the action to take if that condition is true. Evaluation of a cond expression iterates through argument until an argument with a true condition is found. When writing a cond expression, make sure that at least one of the conditions will be true for any argument. A common way to ensure this is to end the list of cond arguments with an expression whose condition is t. This is illustrated below.
>(if (= 1 0) 'a 'b) B >(cond ((= 1 0) 'x) ((= 2 3) 'y) (t 'z)) Z
>(null nil) T >(null 'a) NIL >(null '(c d)) NIL
>(listp '(1 2 3)) T >(listp 'a) NIL >(atom '(1 2 3)) NIL >(atom 'a) T
>(car '(a b)) A >(cdr '(a b)) (B) >(car '((c d) (e f))) (C D) >(cdr '((c d) (e f))) ((E F)) >(car nil) NIL >(cdr nil) NIL >(rest '(a b)) (B) >(first '(a b)) A
>(cons 'a '(b c)) (A B C) >(list 'a 'b 'c) (A B C) >(append '(a) '(b c)) (A B C)
>(let ((a 4)) (* a 2)) 8 >(let ((a 3) (b 9)) (/ b a)) 3 >(let ((a 3)) (let ((a 4)) (* a a))) 16
>(defun double (x)
(* 2 x)
)
DOUBLE
>(double 10)
20
>(defun listdouble (l)
(append l l)
)
LISTDOUBLE
>(listdouble '(a b c))
(A B C A B C)
>(defun fibonacci (x)
(cond
((<= x 1) 1)
(t (+ (fibonacci (- x 1)) (fibonacci (- x 2))))
)
)
FIBONACCI
>(fibonacci 5)
8
>(defun reverse (l)
(cond
((null l) nil)
(t (append (reverse (cdr l)) (list (car l))))
)
)
Warning: REVERSE is being redefined.
REVERSE
>(reverse '(a b c))
(C B A)
>(defun doubleexpr (s) (list '* 2 s) ) DOUBLEEXPR >(doubleexpr 5) (* 2 5) >(doubleexpr 'a) (* 2 A)
>;this is a comment (+ 1 2) 3
gcl -eval '(load "hw1.lsp" )'
(format *query-io* "Type something here: ") (let ((response (read-line *query-io*))) (format *query-io* "Your response was ~A~%" response) )If we run the code from the shell like so, we will see something like this. The bold characters are the ones I typed.
{landfair} 36> gcl -eval '(load "askquestion.lsp" )'
GCL (GNU Common Lisp) Version(2.3) Mon Mar 13 14:49:55 PST 2000
Licensed under GNU Library General Public License
Contains Enhancements by W. Schelter
Type something here: foo foo foo
Your response was foo foo foo
The format operator takes format strings that may remind you of C's printf.
One useful and non-obvious format string is demonstrated below:
>(string 'foo) "FOO" >(string-equal "yes" "Yes it is" :start1 0 :end1 2 :start2 0 :end2 2) TRob Adams found these goodies on the CL Cookbook (see link above):
(defun explode-iter (string current)
(if (= current (array-total-size string))
nil
(cons (aref string current) (explode-iter string (+ current 1)))
)
)
(defun explode (string)
(explode-iter string 0)
)
>(list '+ 3 4) (+ 3 4) >(eval (list '+ 3 4)) 7
A closure is defined as a double whose two elements are a pointer to code and a pointer to an environment. In the adder example below, the reason we need the "environment pointer" is that we need a way to remember what n was bound to at the time that (adder 3) was created.
This particular "adder" example comes from the CL Cookbook.
>(defun adder (n)
(function (lambda (x) (+ x n)))
)
ADDER
>(adder 3)
(LAMBDA-CLOSURE ((N 3)) () ((ADDER BLOCK #<@001C2F40>)) (X) (+ X N))
>(apply (adder 3) '(4))
7
>(funcall (adder 3) 4)
7
>(mapcar (adder 3) '(1 2 3 4))
(4 5 6 7)
Given these definitions, we can define our own mapcar by recursively applying funcall.
>(defun adder (n)
#'(lambda (x) (+ x n))
)
ADDER
>(adder 3)
(LAMBDA-CLOSURE ((N 3)) () ((ADDER BLOCK #<@001C2ED8>)) (X) (+ X N))
>(funcall (adder 3) 4)
7
There are two slightly different ways of using mapcar. One is by passing it a lambda block,
which is created by simply prepending the #' in front of the function name. The other is to
pass it a closure:
>(defun increment (i) (+ i 1) ) INCREMENT >#'increment (LAMBDA-BLOCK INCREMENT (I) (+ I 1)) >(mapcar #'increment '(1 2 3)) (2 3 4) >#'(lambda (x) (increment x)) (LAMBDA-CLOSURE () () () (X) (INCREMENT X)) >(mapcar #'(lambda (x) (increment x)) '(1 2 3)) (2 3 4)
>(defun increment (i) (+ i 1) ) INCREMENT >(defun square (z) (* z z) ) SQUARE >(defun compose (f g) #'(lambda (x) (funcall f (funcall g x))) ) COMPOSE >(funcall (compose #'increment #'square) 3) 10
>(defun printthree (arg1 arg2 arg3)
(format *query-io* "arg1 = ~A, arg2 = ~A, arg3 = ~A~%" arg1 arg2 arg3)
)
PRINTTHREE
>(printthree 3 4 4)
arg1 = 3, arg2 = 4, arg3 = 4
NIL
> (defun curry (function &rest args)
(function (lambda (&rest more-args)
(apply function (append args more-args)))))
CURRY
>(curry #'printthree 'a)
(LAMBDA-CLOSURE
((ARGS (A))
#'(LAMBDA-BLOCK PRINTTHREE (ARG1 ARG2 ARG3)
(FORMAT *QUERY-IO* "arg1 = ~A, arg2 = ~A, arg3 = ~A~%" ARG1
ARG2 ARG3)))
() ((CURRY BLOCK #<@001C2F48>)) (&REST MORE-ARGS)
(APPLY FUNCTION (APPEND ARGS MORE-ARGS)))
>(apply (curry #'printthree 'a) '(b c))
arg1 = A, arg2 = B, arg3 = C
NIL
>(curry #'printthree 'a 'b)
(LAMBDA-CLOSURE
((ARGS (A B))
#'(LAMBDA-BLOCK PRINTTHREE (ARG1 ARG2 ARG3)
(FORMAT *QUERY-IO* "arg1 = ~A, arg2 = ~A, arg3 = ~A~%" ARG1
ARG2 ARG3)))
() ((CURRY BLOCK #<@001C2F30>)) (&REST MORE-ARGS)
(APPLY FUNCTION (APPEND ARGS MORE-ARGS)))
>(apply (curry #'printthree 'a 'b) '(c))
arg1 = A, arg2 = B, arg3 = C
NIL
>(defun uncurry (f)
#'(lambda (x y) (funcall (funcall f x) y))
)
>(defun uncurry (f)
#'(lambda (x y) (funcall (funcall f x) y))
)
UNCURRY
>(uncurry (curry #'+ 1))
(LAMBDA-CLOSURE
((F (LAMBDA-CLOSURE ((ARGS (1)) #'#) ()
((CURRY BLOCK #<@001C2E90>)) (&REST MORE-ARGS)
(APPLY FUNCTION (APPEND ARGS MORE-ARGS)))))
() ((UNCURRY BLOCK #<@001C2E88>)) (X Y)
(FUNCALL (FUNCALL F X) Y))