functional programming: lisp

31
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site). • First interactive, interpreted language Dynamic typing: values have types, variables do not • Garbage-collected Ability to form program fragments and execute. Extensible: multiple dialects, implementations. Convenient testbed for language design experiments Main descendants: Scheme (compact) Common Lisp (massive). Statically typed functional languages: ML

Upload: branden-gonzalez

Post on 31-Dec-2015

44 views

Category:

Documents


0 download

DESCRIPTION

Functional programming: LISP. Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site). First interactive, interpreted language Dynamic typing: values have types, variables do not Garbage-collected - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Functional programming: LISP

Functional programming: LISP

• Originally developed for symbolic computing• Main motivation: include recursion (see McCarthy

biographical excerpt on web site).• First interactive, interpreted language• Dynamic typing: values have types, variables do not• Garbage-collected • Ability to form program fragments and execute.• Extensible: multiple dialects, implementations.

Convenient testbed for language design experiments• Main descendants: Scheme (compact) Common Lisp

(massive). Statically typed functional languages: ML

Page 2: Functional programming: LISP

Uniform syntax: lists

• Expressions are either atoms or lists• atoms are numeric or symbols• lists nest, to form full trees• Syntax is simple because programmer supplies what

would otherwise be the internal representation of a program:

(+ ( * 10 12) (* 7 11)) evaluates (10*12 + 7*11)• A program is a list:

(define (factorial n) (if (eq n 0) 1

( * n (factorial (- n 1))))

Page 3: Functional programming: LISP

List manipulation

• Three primitives and one constant– get head of list: car– get rest of list: cdr– add an element to a list: cons– null list: nil or ()

• Add equality ( = or eq) and recursion, and this is a universal model of computation

Page 4: Functional programming: LISP

Rule of evaluation

• A number evaluates to itself• An atom evaluates to its current binding• A list is a computation.

– Its first element must evaluate to an operation– the remaining elements are actual parameters– the result is the application of the operation to the

evaluated actuals

Page 5: Functional programming: LISP

Quoted data

• If every list is a computation, how do we describe data?

• Another primitive: quote

(quote (1 2 3 4))

=> (1 2 3 4)

(quote (this is a simple declarative sentence)

=> (this is a simple declarative sentence)

‘ (this also works)

=> (this also works)

Page 6: Functional programming: LISP

Decomposing a list

(car ‘(this is a list of symbols))

=> this

(cdr ‘(this is a list of symbols))

=> (is a list of symbols)

(cdr ‘(this that))

=> (that) ; a list (cdr ‘(singleton))

=> () ; the empty list

(car ‘()) ; run time error

Page 7: Functional programming: LISP

Building lists

(cons ‘this ‘(that and the other))

=> (this that and the other)

(cons ‘a ‘())

=> (a)

useful shortcut: list

(list ‘a ‘b ‘c ‘d ‘e)

=> (a b c d e)

equivalent to

(cons ‘a (cons ‘b (cons ‘c (cons ‘d (cons ‘e ‘())))))

Page 8: Functional programming: LISP

Control structures

• Conditional

(if condition expr1 expr2)• Generalized form

(cond

(pred1 expr1)

(pred2 expr2)

(else exprn)

Needs special rule: evaluate only the successful entry

if and cond are not regular functions

Page 9: Functional programming: LISP

Function declarations

(define (sqr n) (* n n))• define is also special: body is not evaluated• defines produces a binding: sqr is bound to the body

of the computation:

(lambda (n) (* n n))• define can produce value bindings as well:

(define x 15)

(sqr x)

=> 225

Page 10: Functional programming: LISP

Lambda or no lambda

(define (sqr n) (* n n))And

(define sqr (lambda (n) (* n n)))

Mean the same thing. The advantage of the lambda formulation is one can have nameless functions, e.g.

((lambda (x y) (+ x y)) 5 6)The lambda brackets the formal parameters.

Page 11: Functional programming: LISP

Eval

McCarthy had the idea: what if I could formulate some data and then execute it;

(eval ‘(+ 5 7))

(eval '(define x 15)) ; creates the binding (x 15)

Page 12: Functional programming: LISP

Recursion

(define (add1 x) (+ x 1)) ; the beginnings of Peano arithmetic

(define (sub1 x) (- x 1))

(define (add x y)

(if (= y 0) x

(add ( (add1 x) (sub1 y))))

(define (times x y)

(cond

((= y 0) 0)

((= y 1) x)

(else (add x (times (x (sub1 y)))))))

Page 13: Functional programming: LISP

Recursion (ii)

(define (exp x y)

(cond

((eq y 0) 1)

(else (times x (exp x (sub1 y))))))

better:

(define (fast-exp x y)

(cond (= y 0) 1)

( (even? y) (square (fast-exp x (/ y 2))))

(else (* x (fast-exp x (- y 1))))))

(define (even? n) (= (remainder n 2) 0)) ; defining a predicate

Page 14: Functional programming: LISP

Recursion on lists

(define (member elmt lis)

(cond

((null? lis) ‘())

((eq elmt (car lis)) lis)

(else (member elmt (cdr lis)))))

convention: return rest of list, starting from elmt, rather than #t or #f

convention: every non-false value is true in a boolean context

Page 15: Functional programming: LISP

Predicates

• If variables are untyped, need run-time tests to determine kind:

symbol?

number?

list?

null?

zero?

Syntax conventions differ in different dialects: symbolp, numberp, listp, zerop...

Page 16: Functional programming: LISP

Functional arguments(functional = a function that takes functions

as arguments) (define (map fun lis)

(cond

((null? lis) ‘())

(cons (fun (car lis)) (map fun (cdr lis)))))

(map sqr (map sqr ‘( 1 2 3 4))

=> (1 16 81 256)

Page 17: Functional programming: LISP

Environments

• An environment describes the current bindings of symbols

• A binding is a pair: (symbol value)• A frame is a list of bindings (activation record), i.e. an

association list: ((s1 v1) (s2 v2)…)• An environment is a list of frames• In some cases we can treat the environment as a

single association list (e.g. with dynamic binding)

Page 18: Functional programming: LISP

Procedures and their environment

• A function has three components: a list of formals, a body, and environment of definition. Formals and body are represented by a lambda expression:

(lambda (f1 f2 ..) expr)• A function is evaluated in its environment of definition

(lexical scoping) after adding the current bindings of the actuals (activation record)

• The definition must capture all three components

(define (make-procedure spec body env)

(list ‘procedure (make-lambda spec body) env))

make-procedure is called by eval to evaluate a define

Page 19: Functional programming: LISP

Scoping Rules

Consider the following examples:

(define x 5)

(define sqr (lambda (z) (* z z )))

(sqr x) ; yields 25

(define addto (lambda (y) (define x 6) (+ x y)))

(addto 9) ; yields 15 given definition of x as 6

(sqr x) ; what should this give?

Page 20: Functional programming: LISP

Scoping Rules 2

Because Scheme is “lexically scoped”, the answer is still 25. The scope of the definition of x within “addto” is just that function.

Lexical scoping: scope of variable is defined by text of program.

A “dynamically scoped” Lisp variant would simply take the last definition of x.

Page 21: Functional programming: LISP

Now Consider this

(define x 5)

(define sqr (lambda (z) (* z z )))

(sqr x) ; yields 25

(define x 8)

(sqr x)

Page 22: Functional programming: LISP

x has been redefined in the same scope as in its first definition, so x changes

Therefore answer is 64.

Page 23: Functional programming: LISP

This notion naturally extends to functions(look up “closure” in Scott)

(define (compose f1 f2) (lambda (x) (f1 (f2 x))))(define (sqr x) (* x x))(define fourth (lambda (x) ((compose sqr sqr) x)))(fourth 4) ; yields 256When fourth is called, we need to fetch the

latest definition of sqr at the right level of scoping.

Page 24: Functional programming: LISP

What happens here?

(define (compose f1 f2)

(lambda (x) (f1 (f2 x))))

(define (sqr x) (* x x))

(define fourth (lambda (x)

((compose sqr sqr) x)))

(define (sqr x) (+ x x))

(fourth 4) ; yields 16 (based on latest def of ; sqr at proper scope level

Page 25: Functional programming: LISP

And here?

(define (compose f1 f2)

(lambda (x) (f1 (f2 x))))

(define (sqr x) (* x x))

(define fourth (lambda (x)

((compose sqr sqr) x)))

(define (foo x) (define (sqr x) (+ x x))

(* 2 (sqr x)))

(foo 15) ; yields 60

(fourth 4) ; yields 256

Page 26: Functional programming: LISP

Evaluating a function definition

(define (name binding) (car binding))• results in the binding:

(name

(procedure (lambda (binding) (car binding)) env))

• procedure and lambda are labels to indicate kind• Env is the current environment. At the top level it

includes the binding for car (used in the body) as well as all other predefined symbols.

Page 27: Functional programming: LISP

Other binding constructs

• Local variables

(let

((x 5) (y 10)) ; x and y bound simultaneously

(* x y))

(let*

((x 5) (y (expt x 2)) ; sequential bindings: y after x

(* x y 3))

Page 28: Functional programming: LISP

Binding formals to actuals

(define (make-frame formals actuals)

(cond

(null? formals) ‘()) ; should check (null? actuals) also

( else (cons

(add-assoc (car formals) (car actuals))

(make-frame (cdr formals) (cdr actuals))))))

(define (extend-environment formals actuals env)

(cons (make-frame formals actuals) env)

Page 29: Functional programming: LISP

Self-definition (advanced)

(define (eval exp env) ; the lisp interpreter

(cond

((number? exp) exp) ; numbers are self-evaluating

((symbol? exp) (lookup exp env)) ; a symbol has a binding

((null? exp) ‘())

((eq (car exp) ‘quote) (car (cdr exp))) ; could write cadr

((eq (car exp) ‘car) (car (car (cdr exp)))) ; caadr

((eq (car exp) ‘cdr) (cdr (car (cdr exp)))) : cdadr

(else (apply (eval (car exp) env) ; apply function

(eval-list (cdr exp) env))) ; to arguments

Page 30: Functional programming: LISP

Function application defined (advanced)

(define (apply procedure arguments)

(eval (procedure-body procedure)

(extend-environment

(parameters procedure)

arguments

(environment procedure))))

In words: add actuals to environment, evaluate body of procedure in new environment

Note: environment is in procedure definition (closure)

Page 31: Functional programming: LISP

Association lists

(define (add-assoc symb val env)

(cons (list symb val) env)) ; add a binding

(define (name binding) (car binding)) ; for readability

(define (value binding) (car (cdr binding)));

(define (lookup symb env) ; sequential search

(cond

((null? env) ‘()) ; error detected later

((eq symb (name (car env))) (value (car env))

(else (lookup symb (cdr env)))))