CSE 473 Autumn 1998, Copyright, S. Tanimoto, Univ. of Washington 
Introduction to Artificial Intelligence (Oct 7, 1998)

"More Wonderful Features of Lisp"

More about Symbols


 

Unnamed Functions, LAMBDA, and Closures

Recall functional arguments...
>  (apply #'first  (list '(a b c)))
A

We can create a functional argument for a new function without DEFUN
>  (setq f  #'(lambda (x) (*  x  x)) )
#<function ...>

>  (apply f '(17))
289

An unnamed function is one way to achieve both locality and modularity.

A functional argument may be made from either a named function or an unnamed function.
(setq  f1  #'(lambda (x) (*  x  x)) )

(defun sqr (x) (*  x  x))
(setq  f2  #'sqr)

> (funcall f1 13)
169

>  (funcall  f2  13)
169
 

A closure is a function that captures some state from the environment in which it is created.
It's like a "method" for an object in an object-oriented programming system.

(let ((x  0) (y  0))
  (defun  xcount ()
     (setq x (1+  x))
     (setq y (*  x  x))
      x)
  (defun current-square () y)
 )

> (xcount)
1
>  (current-square)
1
> (xcount)
2
>  (current-square)
4
>  (current-square)
4
>  (xcount)
3
> (current-square)
9

A function can return a new closure as its value.
In this case the closures are created using an unnamed function.
>  (defun make-accumulator ( sound )
       (let ((x  0))
         #'(lambda (delta)  (print  sound)(incf  x  delta))
        )  )
MAKE-ACCUMULATOR

>  (setq accumulate-cents (make-accumulator  'clink))
#<closure...>
>  (setq accumulate-dollars (make-accumulator  'klunk))
#<closure...>
>  (funcall accumulate-dollars 5)
KLUNK
5
>  (funcall accumulate-dollars 7)
KLUNK
12
>  (funcall accumulate-cents 1)
CLINK
1
>  (funcall accumulate-cents 10)
CLINK
11
 
 


 

I/O

Input

Getting an S-expression from the user:

>  (setq  x  (read))
5
5
>  X
5

Another example:

(append '(I think you said)  (list  (read) ) )
OK
(I THINK YOU SAID OK)
 
 

Output

Output with traditional functions:

>  (print 'x)

X
X
>  (prin1 'x)
X
X
>  (terpri)

NIL
>

Formatted output with FORMAT,
analogous to C's printf  function.

>  (format  t  "This is a string.~%")
This is a string.
NIL
>  (format  t  "The sum of ~S plus ~S equals ~S."  2  5  (+ 2  5))
The sum of 2 plus 5 equals 7.
NIL

For file output...

>  (with-open-file (f  "foo.txt" :direction  :output)
        (format  f  "This goes into the file.")
     )

And input ... Note that READ takes only the first S-expression:

>   (with-open-file (f "foo.txt" :direction :input)
         (print (read f)) )

THIS
THIS

 >  (with-open-file (f "foo.txt" :direction :input)
        (setq s (read-line f)) )

"This goes into the file."
 
 

Loading a file of S-expressions to be evaluated:

>  (load "myprogram.lsp")
 


 

Characters, Arrays, and Strings

A character object is denoted using the #\ notation.

>  (setq achar #\a  )
#\a
>  (characterp achar)
T
>  (lower-case-p  achar)
T
>  (upper-case-p  achar)
NIL
 

An array can be created in two ways: with MAKE-ARRAY or with the direct array notation.

>  (setq  my-array   #1a(1 2 3 4))
#(1 2 3 4)

>  (setq  my-array2  (make-array '(4) :initial-contents '(1 2 3 4)) )
#(1 2 3 4)

To access an array, use AREF
>  (aref my-array 3)
4
>  (aref my-array 0)
1

To change the contents of an element, use both SETF and AREF together.
> (setf (aref my-array 0) 'neat)
NEAT
> my-array
#(NEAT  2  3  4)

Strings are sequences of characters.

>  (setq s1 "This is a string.")
"This is a string."

>  (char s1 0)
#\T
>  (char s1  4)
#\space

> (concatenate 'string  s1  s1)
"This is a string.This is a string."
 
 
 


 
 

Macros

 A macro is an operator whose form is evaluated in two phases:
1. macro expansion
2. evaluation of the expansion

;;; SETQ2 is like SETQ but it's the 2nd arg that's quoted.
> (defmacro  setq2 (arg1  arg2)
   (list 'set  arg1 (list 'quote arg2))  )
SETQ2
>   (macroexpand '(setq2 'a (this is a list)))
(SET 'A '(THIS IS A LIST))
T
>  (setq2 'a (this is a list))
(THIS IS A LIST)
>  a
(THIS IS A LIST)
 

;;; Macros can be used to create new functions from symbols.
(defmacro  make-predicate (name)
   (list 'defun (intern (concatenate 'string (string name) "P"))
                  '(arg)
                 (list 'eq 'arg (list 'quote name)) ) )
 

;;;  This one creates a new predicate that returns T if
;;;   its argument is the symbol mentioned in NAME above.
>  (make-predicate crazy)
CRAZYP
>  (crazyp  'crazy)
T
>  (crazyp  2)
NIL
>  (make-predicate funny)
FUNNYP
>  (funnyp 'crazy)
NIL
>  (funnyp 'funny)
T

 
 
 


 
 

Last modified: October 7, 1998

Steve Tanimoto

tanimoto@cs.washington.edu