CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and...
-
Upload
esther-woodhams -
Category
Documents
-
view
214 -
download
0
Transcript of CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and...
CSE 3341/655; Part 4 1
A functional program: Collection of functions
A function just computes and returns a value
No side-effects
In fact: No program variables whose values change!
A function body: Mainly calls to other functions
Languages: LISP, Scheme, ML, Haskell, ...
Functional Programming
CSE 3341/655; Part 4 2
Program just says what is needed, not how to compute it
The “system” figures out the how
DB systems are (sort of) logic programming systems
Languages: Prolog
Logic programming is not very popular except as DBs
Logic Programming
CSE 3341/655; Part 4 3
Must provide:
Suitable data types
Set of primitive functions
A notation for calling functions
Way to construct new functions by composing
existing ones in different ways
Functional Languages (Chap. 10)
CSE 3341/655; Part 4 4
Data Types: Atomic and non-atomic S-expressions (“symbolic
exps.”) Atoms:
Numbers (we use only integers)
Strings: “xyz”, “34” etc.
Symbols (i.e., identifiers): XYZ, AB12, + etc.Some important symbols:
#t (denotes true ; written T in Lisp)#f (denotes false ; written NIL in
Lisp)
Lisp/Scheme Data Types
5
Non-atomic S-expressions:If s1 and s2 are s-expressions, so is (s1 . s2)
Important primitive functions: cons[ s1, s2] = (s1 . s2) car[ (s1 . s2) ] = s1 cdr[ (s1 . s2) ] = s2 cadr[ s ] = car[ cdr[ s ] ]
cadar[ s ] = car[ cdr[ car[ s ] ] ]
Important: Everything in LISP/Scheme is an s-exp.
Important: Best to think in terms of how s-exps are stored internally: binary trees (using pointers)
Lisp/Scheme Data Types (contd.)
CSE 3341/655; Part 4
CSE 3341/655; Part 4 6
List Notation:( ) denotes NIL (6) denotes (6 . NIL)(6 5) denotes (6 . (5 . NIL))(6 5 5) denotes (6 . (5 . (5 . NIL)))((1 . 2) 3) denotes ((1 . 2) . (3 . NIL))((1 . 2) (3 . 4)) denotes ((1 . 2) . ((3 . 4) . NIL))
In general:(s1) denotes (s1’ . NIL) [s1’ : "dot version" of s1 ](s1 s2) denotes (s1’ . (s2’ . NIL))(s1 s2 s3 ... ) denotes (s1’ . (s2’ . (s3’ . NIL))) etc.
List Notation
CSE 3341/655; Part 4 7
The Scheme/LISP interpreter converts everything to “dot” notation; list notation is only for input/output
Convert: ((1 . 3) 2 4) ((1 . 3) (2 . 4)) ((1 . 3) (2 4)) (1 . (2 . NIL)) ((1 . NIL) . (2 . NIL)) ((1 . 2) . NIL)
(1 . (2 . 3)) ((1 3) (2 4))
Consider car, cdr, cddr etc. of ((1 . 2) (3 . 4)), ((1 . 2) . (3 . 4)) etc.
car, cdr, cons are best understood in terms of how they manipulate s-expressions internally.
List Notation (contd.)
CSE 3341/655; Part 4 8
More functions: eq?[ x, y ] : returns #t or #f if x, y are/are not same atom
eq?[ #t, #f ] = #feq?[ #f, #f ] = #teq?[ #f, 5 ] = #f : arguments to eq? must be atoms
pair?[ x ] : returns #t if x is a "pair"; #f otherwisepair?[ (2 . 3) ] = #tpair?[ (2 . #t) ] = #tpair?[ #t ] = #fpair?[ () ] = #f
null?[ x ] : returns #t if x is (); #f otherwise
Built-in Functions
CSE 3341/655; Part 4 9
Standard math functions (arguments must be numbers): +[ 10, -5 ] = 5 -[ 10, -5 ] = 15 *[ 10, -5 ] = -50 /[ 10, 5 ] = 2 /[ 10, 7 ] = 10/7 >[ 10, -5 ] = #t =[ 10, -5 ] = #f ... many others; but we won't use most of them***Introduce actual notation at this point; don't use design
notation***Important: We have not yet seen any Scheme programs The above are just meanings of these built-in functions
Built-in Functions (contd.)
CSE 3341/655; Part 4 10
Important: Atoms are used for three purposes: Constants: numbers, #t, #f (we won't use string
consts.) Function names: car, cdr, eq?, +, >, ... Function parameters (in function definitions)
Important: Distinction between parameters and arguments(also: "formal parameters" and "actual arguments")
Atoms, Parameters, Arguments
CSE 3341/655; Part 4 11
addUpList[ L ] : return sum of nos. in L (a list of nos.)addUpList[ L ] :: ; "design notation", not Lisp/Scheme
[ null?[ L ] 0 | #t +[ car[L], addUpList[ cdr[L] ] ] ]
addUpList[ (2 3 4) ] : returns 9; how does it work? nNil[ n ] : if n is 4 return (NIL NIL NIL NIL)
nNil[ n ] ::[ =[ n, 0] NIL| #t cons[ NIL, nNIL[ -[n, 1] ] ] ]
doubleUp[ s ] :: cons[ s, s ] ; what does it do? length[ L ] :: ; should return length of list L mystery[L] :: nNil[ length[ L ] ] ; what does it do?
Defining New Functions
CSE 3341/655; Part 4 12
Starting Scheme (on stdlinux):% scheme48... welcome, ...Type ,? for help
; type in a Scheme expression; the interpreter evaluates; it, outputs the value, waits for the next Scheme exp.> ,exit
Simplest Scheme expression: constant atoms:% scheme48> 655655
Scheme/Lisp "Programs"
13
Function application: F[a1, a2, a3, ..., an] (F a1 a2 a3 ... an)The interpreter *evaluates* a1, a2, ..., an; binds the resulting values to p1, p2, ..., pn, the pars of F;then it evaluates the body of F (as a Scheme exp)
> (+ (+ 2 3) (* 5 6) ); evaluates (+ 2 3), (* 5 6), binds to pars of +, then ; evaluates body of + [using values bound to pars when ; needed]> (cons (+ 2 3) (* 5 6) ) ; similar; result:(5 . 30)> (cons A B) ; error! "unbound A, B"> (cons #t #f) ; okay! #t, #f evaluate to #t, #f
Scheme/Lisp Expressions
CSE 3341/655; Part 4
CSE 3341/655; Part 4 14
> (quote A) ; Don't evaluate AA
(quote ...) looks like a function call; but it is not; it can't be!
It is a form [also "special form"]; only three special forms
> (cons (cdr (A . B) ) (car (A . B) ) ) ; Error!
> (cons (cdr (quote (A . B)) ) (car (quote (A . B)) ) ) (B . A)
> (cons (quote (cdr (A . B)) ) (quote (car (A . B)) ) ) ???
Quoted expressions
(cond (b1 e1) (b2 e2) ... (bn en) ) : each bi, ei is a Scheme/Lisp expression
To evaluate:Evaluate b1; if value is #t, evaluate e1, return that valueif b1 value is #f, evaluate b2; if #t, eval e2, return that valif b2 value is #f, evaluate b3; if #t, eval e3, return that val...if b(n-1) value is #f, eval bn; if #t, eval en, return that valelse ... error!
(cond( (> 5 3) 3 )( #t (3 . 5) ) )
(cond( (> 3 5) (cons 3 5) )( #t (cons 5 3) ) )
Conditional expressions (Another Special Form)
15CSE 3341/655; Part 4
CSE 3341/655; Part 4 16
(define (F p1 p2 ... pn) ..body (Scheme exp.).. )
> (define (silly p1 p2) 5)
..okay.. [or some such acknowledgment]
> (silly 10 20)5
> (silly (10 . 20) (20 . 30)) Error!> (silly (cons 10 20) (cons 20 30)) 5
> (silly (quote (10 . 20)) (cons 20 30)) 5
Function Definitions (Sp. Form)
CSE 3341/655; Part 4 17
xmemb[x, list] :: ; is x a member of list?[ null?[list] #f | eq?[x, car[list]] #t| #t xmemb[x, cdr[list]] ]
> (define(xmemb x list) ; is x a member of list?(cond
( (null? list) #f )( (eq? x (car list)) #t ) ; quote list?( #t (xmemb x (cdr list) ) ) ) )
; no values returned> (xmemb 3 (quote (2 3 4)) )
#t
Defining new functions (contd)
CSE 3341/655; Part 418
equal[ x, y ] :: ; x and y may not be atoms[ pair?[x] [pair?[y]
[equal[car[x],car[y]] equal[cdr[x],cdr[y]];| #t #f]
| #t #f ] | pair?[y] #f ; why?
| #t eq?[x,y]]> (define (equal x y)
(cond ( (pair? x) (cond ... ) )
( (pair? y) #f ) ( #t (eq? x y)) ) )
> (define (atom? x) ...) ???
Function Definitions (contd.)
CSE 3341/655; Part 4 19
xunion[s1, s2] :: ; union of atomic lists, less duplicates[ null?[s1] --> s2| null?[s2]--> s1| #t --> [ xmemb[car[s1],s2] --> xunion[cdr[s1],
s2]| #t --> cons[ car[s1], xunion[cdr[s1], s2] ] ]
]; better:xunion[s1, s2] ::
[ null?[s1] --> s2| null?[s2]--> s1| xmemb[car[s1],s2] --> xunion[cdr[s1], s2]| #t --> cons[ car[s1], xunion[cdr[s1], s2] ] ]
Defining new functions (contd)
CSE 3341/655; Part 4 20
addUpList[ L ] ::[ null?[ L ] 0 | #t +[ car[L], addUpList[ cdr[L] ] ] ]
> (define (addUpList L)(cond
( (null? L) 0 )( #t (+ (car L) (addUpList (cdr L) ) ) ) ) )
.. okay ..> (addUpList (2 3 4) )
Error! > (addUpList (quote (2 3 4) ) ) 9 ; but how does it work?
Function Definitions (contd.)
CSE 3341/655; Part 4 21
nNil[ n ] ::[ =[ n, 0] NIL| #t cons[ NIL, nNIL[ -[n, 1] ] ] ]
> (define (nNil n)(cond
((= n 0) (quote ()) ) ; why?(#t (cons '() (nNil (- n 1))) ) ) )
doubleUp[ s ] :: cons[ s, s ] (define (dUp s) (cons s s) ) ; need to quote s?
Function Definitions (contd.)
maxList[L] :: ; returns max of number in non-empty list L
; Functional:[ null?[cdr[L]] --> car[L]| >[car[L], maxList[cdr[L]] --> car[L]| #t --> maxList[cdr[L]] ]
; Functional but better:[ null?[cdr[L]] --> car[L]| #t --> bigger[ car[L], maxList[cdr[L]]] ] ; define bigger
; imperative:maxList[L] = max2[car[L], cdr[L]]max2[x, L] ::
[ null?[L] --> x| >[x, car[L]]--> max2[x, cdr[L]]| #t --> max2[ car[L], cdr[L] ] ]
Different styles in Lisp
22CSE 3341/655; Part 4
CSE 3341/655; Part 4 23
How do you obtain first element of a list?
How do you obtain the last element? [watch out!]
How do you append two lists? [No, not just cons!]
How do you reverse a list? [best: use imperative trick]
More functions
CSE 3341/655; Part 4 24
Five types of Lisp expressions ("programs"):
Constants: 4, 5, #t etc.: Evaluate to themselves [4, 5 etc]
Symbols: X, Y, etc.Look them up on the "association" list [a-list].
Function application: (F a1 a2 a3 ... an)F is a (built-in or user-defined) function that expects
n parameters; each ai is a Lisp expression;Evaluate each ai; bind that value aiv to pi, the
corr. parameter, by adding (pi . aiv) to the a-list;then evaluate the body of F
How Lisp interpreter works
CSE 3341/655; Part 4 25
Quoted exp: (QUOTE s) : where s is any s-exp;evaluates to s
Conditional: (COND (b1 e1) (b2 e2) ... (bn en) ) b1, b2, ... and e1, e2, ... are all Lisp expressions; eval. b1, b2, ... to find the first bj that eval's to non-NIL;eval corr. ej & return its value; if all bi's eval to NIL,
error!
Fn. def.: (DEFINE (F p1 ... pn) fe) : F is new fn., p1, ..., pnits parameters, fe the body; save def. on "d-list".
Lisp Exps./How they are eval'd (contd)
Three key functions: eval: evaluates a Lisp-exp.
evcon: evaluates a conditional Lisp-exp.
apply: applies a function to given set of arguments
interpreter[exp, dList] = eval[exp, NIL, dList] ; why?
evcon[pairs, aList, dList] =[ null?[pairs] --> "error"!
| eval[caar[pairs],aList,dList] --> eval[cadar[pairs],aList,dList]
| #t --> evcon[cdr[pairs], aList, dList] ]
Lisp Interpreter (partial) (*in* Lisp!)
26CSE 3341/655; Part 4
eval[ exp, aList, dList] =[ atom?[exp] --> [ int?[exp] --> exp| eq?[exp,#t] --> #t| eq?[exp,#f] --> #f| in?[exp,aList] -->getVal[exp,aList]| #t --> "unbound variable!" ]| atom?[car[exp]] -->[ eq?[car[exp],QUOTE] --> cadr[exp]| eq?[car[exp],COND] -->evcon[cdr[exp], aList, dList]| #t --> apply[car[exp], evlis[cdr[exp],aList,dList],aList, dList] ]| #t --> "error!" ]
Lisp Interpreter (partial) (contd.)
27
CSE 3341/655; Part 4
CSE 3341/655; Part 4 28
Differences (with LISP):
#t and #f : for "true" and "false" [Lisp uses T, NIL for this]
NIL always written as () and is not a normal atom;In fact, Scheme talks of "pairs" vs. "non-pairs",
not "atoms" and "non-atoms"
Scope rule What "scope rule" means How it works in Lisp/Scheme
Elimination of some imperative features
Scheme vs. LISP