#lang racket ;; CSE 413 14au ;; Lecture 6 sample code ;; Hal Perkins ;;;; ;;;; recursion patterns ;;;; ;; augmenting recursion - build up the example one step at a time ;; factorial - classic example (define fact (lambda (n) (if (< n 2) 1 (* n (fact (- n 1)))))) ;; append - build up answer one list element at a time (define app (lambda (lst1 lst2) (if (null? lst1) lst2 (cons (car lst1) (app (cdr lst1) lst2))))) ;; special case of augmenting recursion on lists: map functions ;; result is a new list where each element is some function of ;; the elements from the original list (define square-each (lambda (lst) (if (null? lst) '() (cons (* (car lst) (car lst)) (square-each (cdr lst)))))) ;; map function abstracts out the operation as a parameter (define map-list (lambda (f lst) (if (null? lst) '() (cons (f (car lst)) (map-list f (cdr lst)))))) ;; examples: (map-list (lambda (n) (* n n)) nums) ;; (map-list odd? nums) ;; (map-list pair? lstlst) ;; (map-list list lstlst) ;; (map-list car nestedlst) ;; map is so useful that it is provided in the standard racket library ;; another special case: filter functions ;; result is a list of elements from original list ;; where some predicate is true (define pairs (lambda (lst) (if (null? lst) '() (if (pair? (car lst)) (cons (car lst) (pairs (cdr lst))) (pairs (cdr lst)))))) ;; examples: (pairs lstlst) (pairs nestedlst) ;; as with mapping functions we can abstract out the function ;; structure by making the filter function a parameter ;; (for variety, use cond here instead of nested if expressions) (define filter-list (lambda (f lst) (cond ((null? lst) '()) ((f (car lst)) (cons (car lst) (filter-list f (cdr lst)))) (else (filter-list f (cdr lst)))))) ;; examples: (filter-list even? nums) ;; (filter-list (lambda (x) (> x 0)) nums) ;; (filter-list pair? lstlst) ;; (filter-list number? mixedlst) ;; filter is also a standard function in racket ;; last special case: reducing functions ;; function reduces list to a single element result (define sumlst (lambda (lst) (if (null? lst) 0 (+ (car lst) (sumlst (cdr lst)))))) ;; this can also be parameterized, but here we need both ;; the function and base case value as parameters (define reduce-list (lambda (f id lst) (if (null? lst) id (f (car lst) (reduce-list f id (cdr lst)))))) ;; examples: (reduce-list + 0 nums) ;; (reduce-list * 1 nums) ;; and all of these can be nested. Examples: ;; (reduce-list + 0 (filter-list number? mixedlst)) ;; (reduce-list + 0 (filter-list (lambda (n) (> n 0)) nums)) ;; Racket provides several variants of reduce. The library foldr ;; (fold right) function is essentially the same as our reduce-list ;; return positive numbers in a mixed list (define posnums (lambda (lst) (filter-list (lambda (n) (> n 0)) (filter-list (lambda (x) (number? x)) lst)))) ;; Some useful lists for testing (define nums '(3 -1 413 42 -17 5)) (define mixedlst '(1 cow 17 42 <-good-numbers (bye bye))) (define lstlst '(a (b (c d)) e (f g))) (define nestedlst '((a b c) (p q r) (w x y z))) ;;;; ;;;; functions, environments, and closures (start) ;;;; (define xvii 17) (define add17 (lambda (x) (+ x xvii))) (define compute (lambda (x) (add17 x))) (define x 1) (define addx (lambda (n) (+ x n))) (define test (lambda (x) (addx x))) ;; 2-argument version of (+ a b) (define sum (lambda (a b) (+ a b))) ;; Curried (1-argument) version of sum (define plus (lambda (a) (lambda (b) (+ a b))))