260 likes | 373 Views
COEN 171 - Functional Languages. Functional programming basics Atoms and lists; cons Useful primitive functions Predicates Arithmetic functions Built-in functions Constructing new functions Temporary variable scopes Control structures: if, case, iteration Output Debugging
E N D
COEN 171 - Functional Languages • Functional programming basics • Atoms and lists; cons • Useful primitive functions • Predicates • Arithmetic functions • Built-in functions • Constructing new functions • Temporary variable scopes • Control structures: if, case, iteration • Output • Debugging • Comparing functional and imperative languages
Functional Programming • Recall the concept of a function from mathematics • f(x) = x + 5 f(10) = 15 • g(x) = x / 3 g(10) = 3 1/3 • x is the parameter, everything to right of = is the definition • Functions can be composed • g(f(10)) = g(15) = 5 • f(g(10)) = f(3 1/3) = 8 1/3 • Pure functional programming follows this model: a functional language provides • a set of primitive functions • a set of functional forms to construct complex functions from the primitives • an operation to apply functions • some structure(s) for storing data
LISP and Variants • LISP is the most widely available example of a functional language • Original MIT LISP spawned host of variants • Most widely available now are • Common LISP • Scheme • static scoping • dynamic typing • Function calls are expressed in “Cambridge Polish” • (function-name arg1 arg2 arg3) • In LISP, everything is evaluated unless the programmer explicitly says not to
Atoms and Lists • An atom is • a symbol • a string of letters or digits, not starting with a digit and not including spaces or parentheses • an integer • a real number • nil • the Boolean false value • the empty list • A list is a sequence of atoms and lists surrounded by ( ) and separated by blanks • (John Mary) • (foo (John Mary) 115)
Atoms and Lists (continued) • Lists are composed of nodes, or conses, each of which has a CAR and a CDR • A list is a chain of nodes, each of whose CDRs is either another list or the empty list • the CARs of the nodes of a list are the elements of the list • A dotted list has a last node whose CDR is not nil • we’ll generally deal only with “true lists” ending with a nil CDR CAR CDR John Mary
Primitive Functions • QUOTE is a primitive function to avoid evaluation • essentially makes something a literal • (QUOTE (A B C)) returns a list (A B C) • (QUOTE A) returns an atom A • usually abbreviated ‘A ‘(A B C) • CONS builds a node: the first argument becomes the CAR and the second becomes the CDR • (CONS ‘A ‘B) • (CONS ‘A ‘(B C)) A B A B C
Primitive Functions (continued) • CONS (continued) • (CONS ‘(A B) ‘(C D)) • ((A B) C D) • CONS can be composed • (CONS ‘A • (CONS (CONS ‘B • (CONS ‘C nil)) • (CONS ‘D nil))) • (A (B C) D) • LIST avoids dotted pair problem of previous slide • (LIST ‘A ‘B) C D A B A D B C A B
Primitive Functions (continued) • CONS and LIST build lists • Also need functions to retrieve components of list • CAR returns the CAR of the argument list • (CAR (CONS ‘(A B) ‘(C D)) • (A B) • CDR returns the CDR of the argument list • (CDR (CONS ‘(A B) ‘(C D)) • (C D) • Also want a way to assign a name to a list • (DEFINE LIST1 (CONS ‘A (CONS (CONS ‘B (CONS ‘C nil)) • (CONS ‘D nil)))) • (A (B C) D) • (DEFINE LIST2 ()) • (SET! LIST2 (CONS ‘(A B) ‘(C D))) • ((A B) C D)
Primitive Functions (continued) • CAR and CDR can also be composed, and there is even a shorthand notation • (CDR (CDR LIST2)) • (D) • (CDDR LIST2) • (CADADR LIST1) • C • Works for up to 4 compositions • NOTE that SET! violates the definition of the pure functional model C D LIST2 A B A D LIST1 B C
Predicates • Predicates are LISP primitive functions that return a true or false value • in Scheme, false is #f, everything else is true • in Common LISP, false is nil, everything else is true • By convention, predicates usually have names that end in P (Common LISP) or ? (Scheme) • (atom? X) returns true if X is an atom • (list? X) returns true if X is a list • (number? X) returns true if X is a numeric value • (zero? X) • (positive? X) • (negative? X) • (null? X) returns true if X = nil • (not X) performs a Boolean negation of the value in X
Arithmetic Functions • Operations • (+ X Y) or (+ X Y Z ... W) • (- X Y) X - Y • (* X Y) or (* X Y Z ... W) • (/ X Y) X / Y • (remainder X Y) • (modulo X Y) • (abs X) • Testing • (EQ? X Y) returns true if X and Y are the same object • (EQUAL? X Y) returns true if X and Y print out the same • (EQUAL 2 2.0) returns #f • (= X Y) return true based on numeric equality • also <, <=, >, >=
Useful Built-in Functions • List manipulations • (LENGTH X) returns number of top level nodes in list X • (LENGTH LIST1) returns 3 • (LAST X) returns last cons cell at top level of list X • (LAST LIST1) returns (D) • (FIRST X) returns first element of list X • similarly SECOND, ..., TENTH • (LIST-REF X num) returns the (num)th element of list X, where the first element has index 0 • (APPEND X Y ... Z) copies all the lists except the last and returns a list with the copy of X followed by the copy of Y followed by... followed by the original of Z • (APPEND! X Y ... Z) appends lists without copying • not a part of standard Scheme • (REVERSE X) returns a copy of list X with top level reversed • (REVERSE! X) reverses without copying
Constructing New Functions • (DEFINE (name param1 ... paramk) expr1 ... expn ) • defines a new function name with arguments param1 to paramk, with “body” expr1 to expn; value returned is last expression evaluated • parameter values are not changed • (DEFINE (second L) (CAR (CDR L))) • returns the CAR of the second top level node in L • (DEFINE X ‘(A B C D)) • (SECOND X) • returns B • Then writing a program in LISP consists of defining functions which use the built-in functions, which in turn are called by higher level definitions, until the top level program is a single function call
Temporary Variable Scopes • LET is the Scheme mechanism for temporarily binding values to names • (LET ( • (name_1 expression_1) • (name_2 expression_2) • <S-expressions> • )) • Evaluate expression_i and bind result to name_i • Name_1 and name_2 can only be used in the <S-expressions> in the body of the LET • static scoping • name_i can’t have a different value assigned
Conditional Control Structures • COND is like a nested if-then-else • COND has sets of (logical predicate) (expression) pairs • each predicate is evaluated in turn, first one that’s true has expression executed and value returned as result • (DEFINE (factorial N) • (COND ((< N 0) nil) • ((= N 1) 1) • (ELSE (* N (factorial (- N 1)))))) • expressions can be expression sequences • IF is a simple if-then or if-then-else • (IF (ZERO? X) (+ Y X) (/ Y X)) • then or else clause can be sequences using begin • (IF (ZERO? X) (BEGIN (+ X 1) (+ Y X)) (/ Y X))
Conditional Control Structures (continued) • Logical connectives • (AND expr1 expr2 expr3 ...) evaluates the expressions in turn until #f is found [one is false]; if never found, result of last expression evaluation is returned • (AND (= 2 2) (> 2 1)) returns #t • (AND (= 2 2) (< 2 1)) returns #f • (OR expr1 expr2 expr3 ...) works same way except evaluation stops when first #t result is found; if never found, return result of last expression evaluation • (OR (= 2 2) (< 2 1)) returns #t
Example (DEFINE (MEMBER ATM LIS) (COND ((NULL? LIS) #f) ((EQ? ATM (CAR LIS)) #t) (ELSE (MEMBER ATM (CDR LIS))))) (DEFINE (MYST LIST1 LIST2) (COND ((NULL? LIST1) ()) ((MEMBER (CAR LIST1) LIST2) (CONS (CAR LIST1) (MYST (CDR LIST1) LIST2))) (ELSE (MYST (CDR LIST1) LIST2))))
Iteration • DO is an iteration construct that allows for local variables • (DO ((var init step)...) (test expr1 expr2 ...) body1...) • assign all init values to vars • evaluate test • if true, evaluate expr1, expr2...; return value of last expr as value of DO and terminate • if false, evaluate body1, body2,...; evaluate step expressions and assign to vars; re-evaluate test • Example (DEFINE (POWER M N) (DO ((RESULT 1 (* M RESULT)) (EXPON N (- EXPON 1))) ((ZERO? EXPON) RESULT) ; NOTE NO BODY!! ) )
Output • (NEWLINE) skips to beginning of new line • (DISPLAY EXPRESSION) outputs value of expression • To record screen output • (TRANSCRIPT-ON “filename”) • (TRANSCRIPT-OFF) stops recording
Debugging Helps • (LOAD “filename”) loads a text file into Scheme • (DEBUG) invokes debugger after error • (TRACE function-name) traces entry and exit from function named • (TRACE-ENTRY) or (TRACE-EXIT) trace one or the other • (UNTRACE function-name) stops tracing • (BREAK function-name) causes a breakpoint on entry to and exit from function named • (BREAK-ENTRY) and (BREAK-EXIT) break on one or the other • (UNBREAK function-name) kills breakpoint • (*args*) gets value of arguments to function • (*result*) shows value about to be returned at exit • (PROCEED) continues after breakpoint • (EXIT) leaves Scheme • or (QUIT) once broken
Scheme Examples (DEFINE (roulette-wheel bet-1 bet-2) (compare-with-bet (RANDOM 37) bet-1 bet-2)) (DEFINE (compare-with-bet wheel-spin bet-1 bet-2) (IF (OR (= wheel-spin bet-1) (= wheel-spin bet-2)) (DISPLAY “You won! ”) (DISPLAY “You lost! “)) wheel-spin) (RANDOM X) is a built-in function that returns a value between 0 and X (compare-with-bet) returns wheel-spin as a value (the last s-expression evaluated)
Scheme Examples (continued) (DEFINE (leap-year? year) (COND ((divisible? year 400) #t) ((divisible? year 100) #f) ((divisible? year 4) #t) (ELSE #f))) (DEFINE (length list-of-objects) (COND ((NULL? list-of-objects) 0) (ELSE (1+ (length (CDR list-of-objects))))))
Scheme Examples (continued) (DEFINE (maximum list-nums) (COND ((NULL? (CDR list-nums))(CAR list-nums)) (ELSE (LET ((maxtail (maximum (CDR list-nums))) (first (CAR list-nums))) (IF (> first maxtail) first maxtail))))) use recursion to find maximum value in CDR of list, compare to first value in list - maximum is larger of those two
Scheme Examples (continued) (DEFINE (inc-list list-nums) (COND ((NULL? list-nums) NIL) (ELSE (CONS (1+ (CAR list-nums)) (inc-list (CDR list-nums)) ) ) ) ) returns a new list containing all the values of the argument list incremented by 1
Comparing Functional and Imperative PLs • Functional languages eliminate consideration of variable allocation and assignment • programming at higher level • some reduction in execution efficiency • Functional languages have simpler (and more uniform) syntax • only problems are when imperative features (DO) creep in • Simpler to deal with concurrent execution • Much more limited number of trained programmers for functional languages, fewer commercial tools
Executing Scheme Programs • Design Center • type scheme at system prompt • invokes DrScheme programming environment • helpme has good information • Get your own copy • www.cs.indiana.edu/scheme-repository/imp.html • particularly DrScheme or MIT Scheme