Title: Explicit Application of Functions, Functional Arguments and Explicit Evaluation
1Explicit Application of Functions, Functional
Argumentsand Explicit Evaluation
Implicit and explicit application of
functions. APPLY, FUNCALL Treating functions
as data and arguments. Repeated application with
mapping functions MAPCAR Anonymous function
creation with LAMBDA. Closures Function-oriented
encapsulations. Functions that generate
closures. Closures that share data. Evaluation Exp
licit evaluation with EVAL
2Explicit Application of Functions
In Lisp, functions are first class (Lisp)
objects and can be manipulated as data, e.g.,
passed as arguments to other functions. They can
be explicitly (as well as implicitly) applied.
Implicit application of gt ( 1 2 3) 6
Explicit application of gt (apply (function )
(list 1 2 3)) 6
3Functional Arguments
A functional object or functional argument is a
representation of a function that can be passed
as an argument and applied to its own
arguments. Example gt (function car) ltFunction
CARgt gt car ltFunction CARgt These used to be
called funargs but are now usually called
closures.
4Choosing a function to apply
gt (defun do-command (command arglist) (let
(f) (if (equal command '(multiply that))
(setq f ') (setq f ') ) (apply f
arglist) ) ) DO-COMMAND gt (do-command '(add
them) '(8 13)) 21
5Applying a Function to Successive Elements of a
List
Heres a unary function with a funny name gt
(1 20) 21 Heres custom-made recursive
function gt (defun increment-each (lst) (if
(null lst) nil (cons (1 (first lst))
(increment-each (rest lst)) ) )
) INCREMENT-EACH gt (increment-each '(1 2 3 4
99.9)) (2 3 4 5 100.9)
6Applying a Function to Successive Elements of a
List (the MAPCAR way)
Heres a simpler way gt (mapcar '1 '(1 2 3 4
99.9)) (2 3 4 5 100.9) OK for functions that
take multiple args gt (mapcar 'cons '(a b c) '(1
2 3)) ((A . 1) (B . 2) (C . 3))
7Anonymous Functions with LAMBDA
Creating and using a named function gt (defun
cube (x) ( x x x)) CUBE gt (cube 5) 125
Creating and using an unnamed function gt
((lambda (x) ( x x x)) 5) 125 Benefits of
unnamed functions -- Can help achieve locality
of reference, -- Might help keep the name space
unpolluted
8Defining and Using FunctionsWithout DEFUN
Creating and using a function, stored as the
Value of a symbol gt (setq double (function
(lambda (x)( x x)))) ltFunction...gt gt (funcall
double 7) 14
Creating a function, as DEFUN does, but without
it. gt (setf (symbol-function 'triple
(function (lambda (x)( 3 x)))
) ltFunction...gt gt (triple 7) 21
ltFunction...gt is implementation-dependent e.g.,
it could be ltLambda-closure...gt, etc.
9Closures
A closure is a callable functional object that
can use variable bindings in effect when the
closure was created. gt (setq toggle (let
((bit 0)) '(lambda () (setq bit (- 1
bit))) ) ) ltInterpreted Closure (unnamed) _at_
x204c8fcagt gt (funcall toggle) 1 gt (funcall
toggle) 0
10A Function that Makes Closures
gt (defun make-toggle (on-value off-value)
(let ((bit 0)) '(lambda ()
(setq bit (- 1 bit)) (if ( bit 1)
on-value off-value) ) ) ) MAKE-TOGGLE gt
(setq traffic-light (make-toggle 'green
'red) ) ltInterpreted Closure (unnamed) _at_
x204c8fcbgt gt (funcall traffic-light) RED gt
(funcall traffic-light) GREEN
11Calling MAKE-TOGGLE (continued)
gt (setq tide-change (make-toggle
'high-tide 'low-tide) ) ltInterpreted Closure
(unnamed) _at_ x204c8fccgt gt (funcall
tide-change) LOW-TIDE gt (funcall
tide-change) HIGH-TIDE gt (funcall
traffic-light) RED gt (funcall tide-change) LOW-TID
E
12Closures that Share Bindings
gt (defun make-stack () (let ((stack nil))
(cons '(lambda (item) closure for push.
(setq stack (cons item stack)) )
'(lambda () closure for pop. (if
stack (progn (let ((top (first
stack))) (setq stack (rest stack))
top) ) nil) ) ) ) )
13Closures that Share Bindings
gt (setq my-stack-closures (make-stack)) (ltCLOSURE
x204cdegt . ltCLOSURE x204cdfgt) gt (funcall (car
my-stack-closures) 'apple) (APPLE) gt (funcall
(car my-stack-closures) 'pear) (PEAR APPLE) gt
(funcall (cdr my-stack-closures)) PEAR
14Evaluation
- If FORM is a constant, return FORM itself.
- If FORM is a non-constant symbol, and this
evaluation is taking place within the scope of a
lexical binding for it, return the value of the
topmost lexical binding for it, and if not in the
scope of a lexical binding, return the
symbol-value of FORM if any, and if none, issue
an unbound variable error. - IF FORM is not a list, issue an error.
- IF the first element of FORM, which now must be a
list, is the name of a function, or is a LAMBDA
expression, recursively evaluate the remaining
elements of the list as arguments, and then apply
the function to the evaluated arguments, and
return the result. (But give an error if the
wrong number of args were given). - IF the first element of FORM is the name of a
special form, then perform the special evaluation
required by that form and return its value. - IF the first element of FORM is the name of a
macro, apply MACROEXPAND to the form, and then
evaluate the result of that and return whatever
results from this second evaluation. - OTHERWISE issue an error saying that the first
element of FORM was not recognized as a function.
15Calling the Evaluator Explicitly
gt (setq fruit 'apple) APPLE gt (setq apple
'red) RED gt fruit APPLE gt (eval fruit) RED gt
(eval 'fruit) APPLE
16Calling the Evaluator Explicitly (Cont.)
gt (setq exp '( 3 4 ( 5 6) 7 8)) ( 3 4 ( 5 6)
7 8) gt (eval exp) 52 gt (eval (cons ' (rest
exp))) 20160 ( 3 4 ( 5 6) 7 8)
17A Caveat with EVAL
EVAL does not recognize lexical bindings gt (let
((x 5) (exp2 '( 2 3 4 x))) (print
exp2) (print (eval exp2)) ) Error Attempt
to take the value of the unbound variable 'X'.
18A Caveat with EVAL (Cont.)
EVAL does recognize dynamic bindings gt (setq x
0) 0 gt (let ((x 5) (exp2 '( 2 3 4 x)))
(print exp2) (print (eval exp2)) ) 0 The
evaluation of ( 2 3 4 X) takes place within the
body of EVAL (a built-in function) which is
OUTSIDE the lexical scope established by the LET
form. But the global value of X is accessible and
is used.