; Procedures as values ; a neat thing that you can do in Scheme ..... ; you can actually pass procedures as an input to other procedures ; this has some intersting results, in that it allows you to create generic ; versions of some procedures... ; sum-of-first-n, finds the sum of the first n natural numbers (define sum-of-first-n (lambda (n) (if (= n 0) 0 (+ n (sum-of-first-n (- n 1)))))) ; I want to make this generic, so that it will add (PROC n) each time, where ; PROC is the input procedure ; I want generic-sum to return a procedure, which compute the sum of the PROC ; of the first n natural numbers (define generic-sum (lambda (proc) ; since we want to return a procedure, let us make a procedure and then return it ; so we will use LETREC (letrec ((kernel (lambda (n) (if (= n 0) 0 (+ (proc n) (kernel (- n 1))))))) ; now what do I return? ; we just want to return kernel, which we can then use as a new procedure kernel))) (define cube (lambda (n) (* n n n))) ; in order to use the new procedures that we create with generic-sum we need ; to give them names (define sum-of-cubes (generic-sum cube)) ; since sqrt is builtin, let's try sum-of-sqrts (define sum-of-sqrts (generic-sum sqrt)) ;;; factorial: compute the product of positive integers not ;;; greater than a given positive integer ;;; John David Stone ;;; Department of Mathematics and Computer Science ;;; Grinnell College ;;; stone@cs.grinnell.edu ;;; created February 3, 2000 ;;; last revised August 8, 2001 ;;; Given: ;;; NUMBER, an integer. ;;; Result: ;;; PRODUCT, an integer. ;;; Precondition: ;;; NUMBER is positive and exact. ;;; Postcondition: ;;; PRODUCT is the product of the positive integers not ;;; greater than NUMBER. (define factorial (lambda (number) (if (= number 1) 1 (* number (factorial (- number 1)))))) (define sum-of-factorials (generic-sum factorial)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; second day of lab ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; what does the builtin procedure APPLY do? ; basically it is called in the following way: ; (apply PROC LIST) ; then it runs the result when PROC was given the elements of the list as input ; example: (apply + '(1 2 3 4)) ; this is the same as saying (+ 1 2 3 4), which returns 10 ; a similar procedure is called MAP ; the syntax is (map PROC LIST) ; map returns the list that results from execute PROC on each individual element ; of LIST ; example: (map sqrt '(1 4 9 16)) ; will return '(1 2 3 4) ; to illustrate the difference consider the two commands (apply list '(1 2 3 4)) ; which returns (1 2 3 4) and (map list '(1 2 3 4)) ; which retuns ((1) (2) (3) (4)) ; we saw above that (apply + '(1 2 3 4)) returns 10 ; what does (map + '(1 2 3 4)) ; return? ; it just returns (1 2 3 4), because (+ 1) returns 1 ; one distinction you can make is that the procedure you give to MAP must ; be able to take one argument, whereas the procedure given to APPLY typically ; is what we call "variable-arity" in that it can take any number of arguments ; my-apply does the same thing as apply, when the input procedure can take any ; number of arguments, note that this will only work when proc returns the ; same type as the input type (define my-apply (lambda (proc ls) (if (null? ls) (proc) (proc (car ls) (my-apply proc (cdr ls)))))) ; unfortunately this is really limited. it works for (my-apply + '(1 2 3 4)) ; but not for (my-apply list '(1 2 3 4)) ;