Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
PPL
Sequence Interface
(define make-tree
(λ (value children)
(λ (sel)
(sel value children))))
(define root-value
(λ (tree)
(tree (λ (value children)
(value)))))
(define tree-children
(λ (tree)
(tree (λ (value children)
(children)))))
The Sequence Interface
• OOP languages support collections
• FP is better: sequence operations
• Java 8 new feature is sequence operations…
Scheme had it for years!
What is Sequence Interface?
• ADT for lists
• In other words: a barrier between clients
running sequence applications and their
implementations
• Abstracts-away element by element
manipulation
Map
• Applies a procedure to all elements of a list. Returns a list as a result
;Signature: map(proc,sequence)
;Purpose: Apply ’proc’ to all ’sequence’.
;Type: [[T1 -> T2]*LIST(T1) -> LIST(T2)]
;Examples:
;(map abs (list -10 2.5 -11.6 17))
; ==> (10 2.5 11.6 17)
;(map (lambda (x) (* x x)) (list 1 2 3 4))
; ==> (1 4 9 16)
;Post-condition: For all i=1..length(sequence):
resulti = proc(sequencei)
Map Example: scale-list
Scaling list of numbers by a factor
;Signature: scale-list(items,factor)
;Purpose: Scaling elements of a number
list by a factor.
;Type: [LIST(Number)*Number ->
LIST(Number)]
> (scale-list (list 1 2 3 4 5) 10)
(10 20 30 40 50)
Implementation of scale-list
No Map
Map
(define scale-list
(lambda (items factor)
(if (null? items)
(list)
(cons (*
(car items)
factor)
(scale-list
(cdr items)
factor)))))
(define scale-list
(lambda (items factor)
(map
(lambda (x)
(* x factor))
items))
Map Example: scale-tree
Mapping over hierarchical lists
>(scale-tree
(list 1
(list 2 (list 3 4) 5)
(list 6 7))
10)
(10 (20 (30 40) 50) (60 70))
Implementation of scale-tree
No Map
Map
(define scale-tree
(lambda (tree factor)
(cond ((null? tree)
(list))
((not (list? tree))
(* tree factor))
(else
(cons
(scale-tree
(car tree)
factor)
(scale-tree
(cdr tree)
factor))))))
(define scale-tree
(lambda (tree factor)
(map (lambda (sub-tree)
(if (list? sub-tree)
(scale-tree
sub-tree
factor)
(*
sub-tree
factor)))
tree)))
Map in Java
List<Integer> list =
Arrays.asList(1, 2, 3, 4, 5, 6, 7);
//Old way:
for(Integer n: list) {
System.out.println(n);
}
//New way:
list.forEach(n -> System.out.println(n));
//Scheme
(map list (lambda(n) (display n))
Implementation of Map
;Signature: map(proc,items)
;Purpose: Apply ’proc’ to all ’items’.
;Type: [[T1 -> T2]*LIST(T1) -> LIST(T2)]
(define map
(lambda (proc items)
(if (null? items)
(list)
(cons (proc (car items))
(map proc (cdr items))))))
A More General Map
• So far, the procedure can get only a single
parameter: an item in the list
• Map in Scheme is more general: n-ary procedure
and n lists (with same length)
Example:
> (map +
(list 1 2 3)
(list 40 50 60)
(list 700 800 900))
(741 852 963)
Haskell Curry
Function Currying: Reminder
• Technique for turning a function with n
parameters to n functions with a single
parameter
• Good for partial evaluation
Currying
;Type: [Number*Number -> Number]
(define add
(λ (x y)
(+ x y)))
;Type: [Number -> [Number -> Number]]
(define c-add
(λ (x)
(λ (y)
(add x y))))
(define add3 (c-add 3))
(add3 4)
7
Why Currying?
(define add-fib
(lambda (x y)
(+ (fib x) y)))
(define c-add-fib
(lambda (x)
(lambda (y)
(+ (fib x) y))))
(define c-add-fib
(lambda (x)
(let ((fib-x (fib x)))
(lambda (y)
(+ fib-x y)))))
Curried Map Delayed List Naïve
Version:
;Signature: c-map-proc(proc)
;Purpose: Create a delayed map for ’proc’.
;Type: [[T1 -> T2] -> [LIST(T1) -> LIST(T2)]]
(define c-map-proc
(lambda (proc)
(lambda (lst)
(if (empty? lst)
lst
(cons
(proc (car lst))
((c-map-proc proc) (cdr lst)))))))
Curried Map – delay the list
(define c-map-proc
(lambda (proc)
(letrec ((iter (lambda (lst)
(if (empty? lst)
lst
(cons
(proc (car lst))
(iter (cdr lst)))))))
iter)))
Curried Map – delay the proc
;Signature: c-map-list(lst)
;Purpose: Create a delayed map for ’lst’.
;Type: [LIST(T1) -> [[T1 -> T2] -> LIST(T2)]]
(define c-map-list
(lambda (lst)
(if (empty? lst)
(lambda (proc)
lst) ;c-map-list returns a procedure
(let ((mapped-cdr (c-map-list (cdr lst)))) ;Inductive Currying
(lambda (proc)
(cons (proc (car lst))
(mapped-cdr proc)))))))
Filter Homogenous List
Signature: filter(predicate, sequence)
Purpose: return a list of all sequence elements
that satisfy the predicate
Type: [[T-> Boolean]*LIST(T) -> LIST(T)]
Example: (filter odd? (list 1 2 3 4 5)) ==> (1 3 5)
Post-condition: result = sequence {el|el∈sequence and not(predicate(el))}``
Accumulate Procedure Application
Signature: accumulate(op,initial,sequence)
Purpose: Accumulate by ’op’ all sequence
elements, starting (ending)
with ’initial’
Type: [[T1*T2 -> T2]*T2*LIST(T1) -> T2]
Examples: (accumulate + 0 (list 1 2 3 4 5)) ==> 15
(accumulate * 1 (list 1 2 3 4 5)) ==> 120
Interval Enumeration
Signature: enumerate-interval(low, high)
Purpose: List all integers within an interval:
Type: [Number*Number -> LIST(Number)]
Example: (enumerate-interval 2 7) ==> (2 3 4 5 6
7)
Pre-condition: high > low
Post-condition: result = (low low+1 ... high)
Enumerate Tree
Signature: enumerate-tree(tree)
Purpose: List all leaves of a number tree
Type: [LIST union T -> LIST(Number)]
Example: (enumerate-tree (list 1 (list 2 (list 3 4))
5)) ==> (1 2 3 4 5)
Post-condition: result = flatten(tree)
Sum-odd-squares
;Signature: sum-odd-squares(tree)
;Purpose: return the sum of all odd square
leaves
;Type: [LIST -> Number]
(define sum-odd-squares
(lambda (tree)
(accumulate
+
0
(map square
(filter odd?
(enumerate-tree tree))))))
Even Fibonacci Numbers
Without sequence operations:
With sequence operations:
(define even-fibs
(lambda (n)
(letrec
((next
(lambda(k)
(if (> k n)
(list)
(let ((f (fib k)))
(if (even? f)
(cons
f
(next (+ k 1)))
(next
(+ k 1))))))))
(next 0))))
(define even-fibs
(lambda (n)
(accumulate
cons
(list)
(filter
even?
(map fib
(enumerate-interval
0
n))))))
Filter implementation
;; Signature: filter(predicate, sequence)
;; Purpose: return a list of all sequence elements that
satisfy the predicate
;; Type: [[T-> Boolean]*LIST(T) -> LIST(T)]
(define filter
(lambda (predicate sequence)
(cond ((null? sequence) sequence)
((predicate (car sequence))
(cons (car sequence)
(filter predicate (cdr sequence))))
(else
(filter predicate (cdr sequence))))))
Accumulate Implementation
;;Signature: accumulate(op,initial,sequence)
;;Purpose: Accumulate by ’op’ all sequence elements,
starting (ending)
;;with ’initial’
;;Type: [[T1*T2 -> T2]*T2*LIST(T1) -> T2]
(define accumulate
(lambda (op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence))))))
Enumerate-interval Implementation
;;Signature: enumerate-interval(low, high)
;;Purpose: List all integers within an interval:
;;Type: [Number*Number -> LIST(Number)]
(define enumerate-interval
(lambda (low high)
(if (> low high)
(list)
(cons
low
(enumerate-interval (+ low 1) high)))))
Enumerate-Tree Implementation
;;Signature: enumerate-tree(tree)
;;Purpose: List all leaves of a number tree
;;Type: [LIST union T -> LIST(Number)]
(define enumerate-tree
(lambda (tree)
(cond ((null? tree) (tree))
((not (list? tree)) (list tree))
(else
(append
(enumerate-tree (car tree))
(enumerate-tree (cdr tree)))))))