0% found this document useful (0 votes)
49 views

Functional Languages: CWRU/EECS345/Beer

The document describes functional languages and the functional programming paradigm. It discusses defining features of functional languages like programs being collections of functions without variables or assignment. It then provides an example of defining the factorial function recursively in the Scheme programming language. Scheme is evaluated using substitution semantics, replacing function calls with their defined values in a step-by-step process. The document contrasts the imperative approach to defining factorial with recursion in Scheme. It also covers key concepts in Scheme like values, evaluation, quoting, predicates, equality, and list processing.

Uploaded by

Nguyen Dinh Son
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views

Functional Languages: CWRU/EECS345/Beer

The document describes functional languages and the functional programming paradigm. It discusses defining features of functional languages like programs being collections of functions without variables or assignment. It then provides an example of defining the factorial function recursively in the Scheme programming language. Scheme is evaluated using substitution semantics, replacing function calls with their defined values in a step-by-step process. The document contrasts the imperative approach to defining factorial with recursion in Scheme. It also covers key concepts in Scheme like values, evaluation, quoting, predicates, equality, and list processing.

Uploaded by

Nguyen Dinh Son
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Functional Languages

• Defining features
➪ Programs as collections of functions
➪ Function call (applicative)
➪ No variables (but names are allowed)
➪ No assignment
➪ No iteration (recursion)
• Grounded in recursive function theory (Church’s λ calculus)
• First introduced in Lisp (developed by John McCarthy in the
late 1950s)

CWRU/EECS345/Beer
Scheme
• Scheme is a minimalist Lisp
• Developed by Steele and Sussman (1975-1978)
• ANSI standard since 1990
• Popular teaching language since Abelson and Sussman’s
“Structure and Interpretation of Computer Programs” (1985)

CWRU/EECS345/Beer
Functional Example: Scheme
fact(n) ≡ n × (n-1) × ... × 1

fact(n) = n × fact(n-1)
fact(0) = 1

(define (fact n)

(if (= n 0)



1



(* n (fact (- n 1)))))

• Call as (fact 10)


• Prefix notation
➪ n * fact(n - 1) ⇒ (* n (fact (- n 1)))
➪ Easier to express n-ary functions: (+ 1 2 3 4 5)
• No type declarations (run-time typing of data)

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)

(if (= n 0)



1



(* n (fact (- n 1)))))

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)
(* 10 (fact 9))
(if (= n 0)



1



(* n (fact (- n 1)))))

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)
(* 10 (fact 9))
(if (= n 0)
(* 10 (* 9 (fact 8)))


1



(* n (fact (- n 1)))))

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)
(* 10 (fact 9))
(if (= n 0)
(* 10 (* 9 (fact 8)))


1
(* 10 (* 9 (* 8 (fact 7))))
(* 10 (* 9 (* 8 (* 7 (fact 6)))))



(* n (fact (- n 1)))))
(* 10 (* 9 (* 8 (* 7 (* 6 (fact 5))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (fact 4)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (fact 3)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (fact 2)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (fact 1))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (* 1 (fact 0))))))))

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)
(* 10 (fact 9))
(if (= n 0)
(* 10 (* 9 (fact 8)))


1
(* 10 (* 9 (* 8 (fact 7))))
(* 10 (* 9 (* 8 (* 7 (fact 6)))))



(* n (fact (- n 1)))))
(* 10 (* 9 (* 8 (* 7 (* 6 (fact 5))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (fact 4)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (fact 3)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (fact 2)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (fact 1))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (* 1 (fact 0))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (* 1 1))))))))))

CWRU/EECS345/Beer
Recursive Factorial in Scheme
(define (fact n)
(fact 10)
(* 10 (fact 9))
(if (= n 0)
(* 10 (* 9 (fact 8)))


1
(* 10 (* 9 (* 8 (fact 7))))
(* 10 (* 9 (* 8 (* 7 (fact 6)))))



(* n (fact (- n 1)))))
(* 10 (* 9 (* 8 (* 7 (* 6 (fact 5))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (fact 4)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (fact 3)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (fact 2)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (fact 1))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (* 1 (fact 0))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (* 1 1))))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 1)))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 2))))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 6)))))))
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 24))))))
(* 10 (* 9 (* 8 (* 7 (* 6 120)))))
(* 10 (* 9 (* 8 (* 7 720))))
(* 10 (* 9 (* 8 5040)))
(* 10 (* 9 40320))
(* 10 362880) Substitution Semantics
3628800
(β reduction)
CWRU/EECS345/Beer
Imperative vs. Functional
int fact(int n) (define (fact n)
{
(if (= n 0)

int result;


1

result = 1;


(* n (fact (- n 1)))))

while (n > 0) {


result = result * n;


n = n - 1;

}

return result;
int fact(int n)
}
{

if (n == 0)


return 1;

else


return n * fact(n-1);
}

CWRU/EECS345/Beer
CWRU/EECS345/Beer
Scheme: Values
• Numbers: 5, 3.14, 1/3, 2.1-3i
• Symbols: pi, symbol-table
• Defining global constants
➪ (define pi 3.14159)
➪ pi ⇒ 3.14159
➪ Primitive functions are just symbols that evaluate to
executable code: + ⇒ #<primitive:+>
• Expressions: (+ 1 (* 2 (- pi 1))) ⇒ 5.28318
• Boolean: #f (false) and #t (true)
• Strings: “Hello, world!”
• Lists
➪ A list of symbols and numbers: (a 1 b 2)
➪ The empty list: ()
➪ Lists can be nested: (a (b () c) (1 (2)))

CWRU/EECS345/Beer
Scheme: Evaluation
• The evaluation rule
➪ Constants are self-evaluating: 2 2
➪ Symbols are evaluated by looking up their values:
pi 3.14159
➪ Lists are evaluated by
Evaluate each element
Apply the first element to the remaining elements
(* 2 pi) → (#<primitive:*> 2 3.14159) 6.28318
• if is one of a small number of “special” functions (Why?)

(define (fact n)

(if (= n 0)



1



(* n (fact (- n 1)))))

CWRU/EECS345/Beer
Scheme: Quoting
• A problem: How to stop evaluation?
➪ If pi ⇒ 3.14159, how to manipulate the symbol pi?
➪ If (+ 1 2) ⇒ 3, how to manipulate the list (+ 1 2)?
• A solution: Quoting
• Quoting in English
➪ The word metaphor is very strange
➪ The word “metaphor” is very strange
• Examples
➪ (quote pi) or ‘pi ⇒ pi
➪ ‘(+ 1 2) ⇒ (+ 1 2)
➪ (list (+ 1 2) 3) ⇒ (3 3)
➪ (list ‘(+ 1 2) 3) ⇒ ((+ 1 2) 3)
➪ ‘’pi ⇒ ’pi
(quote (quote pi)) ⇒ (quote pi)

CWRU/EECS345/Beer
Scheme: Predicates
• Is it the empty list: null?
➪ (null? ‘()) ⇒ #t
➪ (null? 5) ⇒ #f
• Is it a number: number?
➪ (number? 5) ⇒ #t
➪ (number? ‘pi) ⇒ #f but (number? pi) ⇒ #t
• Is it a list: list?
➪ (list? ‘(+ 1 2)) ⇒ #t but (list? (+ 1 2)) ⇒ #f
➪ (list? ‘()) ⇒ #t
• Others: boolean?, string?, symbol?, etc.

CWRU/EECS345/Beer
Scheme: Equality
• Two objects are equivalent if they have the same structure and
contents
• Examples
➪ (equal? 1 5) ⇒ #f
➪ (equal? ‘(1 2) ‘(1 2)) ⇒ #t
➪ (equal? 5 ‘(5)) ⇒ #f
➪ (equal? ‘(1 2) ‘(2 1)) ⇒ #f
➪ (equal? ‘(1 2 3) ‘(1 (2 3))) ⇒ #f
➪ (equal? ‘() ‘()) ⇒ #t
➪ (equal? 1 1.0) ⇒ #f
• Other kinds of equality: string=?, eqv?, eq?, etc.
➪ (define L ‘(a b c))
➪ (eq? L L) ⇒ #t
➪ (eq? ‘(a b c) ‘(a b c)) ⇒ #f
➪ (equal? ‘(a b c) ‘(a b c)) ⇒ #t

CWRU/EECS345/Beer
Scheme: List Processing
• Putting lists together
➪ (cons ‘a ‘(b c)) ⇒ (a b c)
➪ (append ‘(a) ‘(b c)) ⇒ (a b c)
➪ (list ‘a ‘b ‘c) ⇒ (a b c)
• Challenges
➪ (cons ‘() ‘())
⇒ (())
➪ (append ‘() ‘())
⇒ ()
➪ (list ‘() ‘())
⇒ (()())

CWRU/EECS345/Beer
Scheme: List Processing
• Taking lists apart
➪ (car ‘(a b c)) ⇒ a (first)
➪ (cdr ‘(a b c)) ⇒ (b c) (rest)
• Challenges
➪ (car (cdr ‘(a b c)))
⇒b
➪ (cdr (car ‘(a b c)))
⇒ ERROR
➪ (define L ‘(a (b (c))))
➪ (cons (car (car (cdr L))) (cdr (car (cdr L))))
⇒ (b (c))
(cdr L) ⇒ ((b (c)))
(car (cdr L)) ⇒ (b (c))
(car (car (cdr L))) ⇒ b
(cdr (car (cdr L))) ⇒ ((c))

CWRU/EECS345/Beer
Box and Arrow Notation
The list (A B C)

A B C

(car ‘(A B C))

A B C

(cdr ‘(A B C))

A B C
CWRU/EECS345/Beer
Box and Arrow Notation
(cons ‘A ‘(B C))

A B C

A B C
CWRU/EECS345/Beer
Box and Arrow Notation
(list ‘A ‘B ‘C)

A B C
(append ‘(A B) ‘(C))

A B C

CWRU/EECS345/Beer
User-Defined List Functions
(define (my-length l)

(if (null? l)



0



(+ 1 (my-length (cdr l)))))

(my-length ‘(a b c)) ⇒ 3

(define (my-reverse l)

(if (null? l)



‘()



(append (my-reverse (cdr l)) (list (car l)))))

(my-reverse ‘(a b c)) ⇒ (c b a)

CWRU/EECS345/Beer
User-Defined List Functions
(replace ‘a ‘b ‘(a b c)) ⇒ (b b c)

(define (replace x y l)

(cond ((null? l) ‘())



((equal? x (car l))




(cons y (replace x y (cdr l))))



(#t (cons (car l) (replace x y (cdr l))))))

Case 1: (replace ‘a ‘b ‘()) ⇒ ()


Case 2: (replace ‘a ‘b ‘(a ...)) ⇒ (b ...)
Case 3: (replace ‘a ‘b ‘(? ...)) ⇒ (? ...)

(replace ‘a ‘b ‘(a (a (a (a))))) ⇒ (b (a (a (a))))

???
CWRU/EECS345/Beer
User-Defined List Functions
(define (replace x y l)

(cond ((null? l) ‘())



((equal? x (car l))




(cons y (replace x y (cdr l))))



((list? (car l))




(cons (replace x y (car l))





(replace x y (cdr l))))



(#t (cons (car l) (replace x y (cdr l))))))

(replace ‘a ‘b ‘(a (a (a (a)))))


⇒ (b (b (b (b))))

CWRU/EECS345/Beer
Scheme: Local Bindings
(define (replace x y l)

(cond ((null? l) ‘())



((equal? x (car l))




(cons y (replace x y (cdr l))))



((list? (car l))




(cons (replace x y (car l))





(replace x y (cdr l))))



(#t (cons (car l) (replace x y (cdr l))))))

CWRU/EECS345/Beer
Scheme: Local Bindings
;;; Replace X with Y in L
;;; Version 3 - RDB
(define (replace x y l)

(if (null? l)



‘()


(let ((first (car l))



(rest (cdr l)))



(cond ((equal? x first)





(cons y (replace x y rest)))





((list? first)





(cons (replace x y first)





(replace x y rest)))




(#t (cons first (replace x y rest)))))))

CWRU/EECS345/Beer
Variables vs. Named Values
(let ((x 1))
(+ x x))
⇔ (+ 1 1)

{

{
int x = 1;
1 = 1 + 1;
x = x + x;
}
}

{ {


int x = 1, y = 1; int x, y;
x = x + x; x = 1 + 1;
y = x; y = 1;
} }
CWRU/EECS345/Beer
Symbolic Manipulation
(define (deriv expr var)

(cond


((number? expr) 0)


((equal? expr var) 1)


((symbol? expr) 0)


((equal? (car expr) ‘+)


(list ‘+



(deriv (car (cdr expr)) var)



(deriv (car (cdr (cdr expr))) var)))


...))

(deriv ‘(* c x) ‘x) ⇒ (+ (* c 1) (* x 0))

CWRU/EECS345/Beer
Higher-Order Functions
(define (double-list l)

(if (null? l)



‘()



(cons (+ (car l) (car l))




(double-list (cdr l)))))

(double-list ‘(1 2 3)) ⇒ (2 4 6)

(define (square-list l)

(if (null? l)



‘()



(cons (* (car l) (car l))




(square-list (cdr l)))))

(square-list ‘(1 2 3)) ⇒ (1 4 9)

CWRU/EECS345/Beer
Higher-Order Functions
(define (my-map fn l)

(if (null? l)



‘()



(cons (fn (car l))




(my-map fn (cdr l)))))

(define (double x) (+ x x))


(define (square x) (* x x))

(my-map double ‘(1 2 3)) ⇒ (2 4 6)


(my-map square ‘(1 2 3)) ⇒ (1 4 9)

(works because double ⇒ #<procedure:double>)

(my-map number? ‘(1 a b -1.23)) ⇒ (#t #f #f #t)


CWRU/EECS345/Beer
Anonymous Functions
(lambda (x) (+ x x)) ⇒ #<procedure:XXX>

(my-map (lambda (x) (+ x x)) ‘(1 2 3)) ⇒ (2 4 6)


(my-map (lambda (x) (* x x)) ‘(1 2 3)) ⇒ (1 4 9)

((lambda (x) (+ x x)) 2) ⇒ 4

(define (double x) (+ x x))


� � � ⇔
(define double (lambda (x) (+ x x)))

CWRU/EECS345/Beer
Let and Lambda
• Let is just syntactic sugar for lambda

(let ((a 1)



(b 2))

(+ a b))

((lambda (a b) (+ a b)) 1 2)

CWRU/EECS345/Beer
Higher-Order Functions
Function composition: f °g(x) = f(g(x))

(define (compose f g)
(lambda (x) (f (g x)))

(define (double x) (+ x x))


(define (square x) (* x x))

(define square-double (compose square double))

(square-double 3) ⇒ 36
((compose square double) 3) ⇒ 36

CWRU/EECS345/Beer
Eval
• The evaluation problem revisited
➪ (+ 1 2) ⇒ 3
➪ ‘(+ 1 2) ⇒ (+ 1 2)
• We can turn this “problem” into a feature
• We can write programs to build other programs!
➪ (list ‘+ 1 2) ⇒ (+ 1 2)
➪ (define (build-call fn args) (cons fn args))
➪ (build-call ‘+ ‘(1 2)) ⇒ (+ 1 2)
• But how do we make these new programs execute?
• We need a kind of “inverse” of quote
(instead of stopping evaluation , we want an extra evaluation)
➪ (eval ‘(+ 1 2)) ⇒ 3
➪ (eval (list ‘+ 1 2)) ⇒ 3
• The basis of a powerful macro facility

CWRU/EECS345/Beer
Common Lisp
• Attempt to define a common core across many Lisp dialects
• First version developed from 1981-1984 (CLtL 1)
• ANSI working group formed in 1986
• Revised Common Lisp became an ANSI standard in 1994
• While Scheme is minimalist, Common Lisp is maximalist
• CLtL 2 is over 1000 pages long!
• LispWorks, Allegro Common Lisp, OpenMCL

CWRU/EECS345/Beer
CWRU/EECS345/Beer
From Scheme to Common Lisp
• Defining named globals
➪ (define PI 3.14159) vs. (defvar PI 3.14159)
➪ Also defconstant and defparameter
• Defining functions
➪ (define (f x) ...) vs. (defun f (x) ...)
• Predicate Names
➪ null? vs. null
➪ number? vs. numberp, etc.
➪ equal? vs. equal
• Invoking functions bound to symbols
➪ + vs. #’+
➪ (f x) vs. (funcall f x)
• The empty list: () vs. ()/nil
• Booleans: #t/#f vs. t/nil

CWRU/EECS345/Beer
Other Functional Languages
• ML
fun fact n =
if n = 0 then 1 else n * fact(n-1);
• Haskel
fact 0 = 1
fact n = n * fact(n-1)
• Dylan
define method fact(n)
if (n = 0) 1
else n * fact(n-1)
end
end;

CWRU/EECS345/Beer

You might also like