;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname returning_a_function) (read-case-sensitive #t) (teachpacks ((lib "draw.ss" "teachpack" "htdp") (lib "hangman.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "draw.ss" "teachpack" "htdp") (lib "hangman.ss" "teachpack" "htdp"))))) ;;; These examples cover material in Ch. 22 ;; In Scheme functions are "first-class citizens" ;; You can write a function that builds and ;; returns functions ;; why would we need such a thing? ;; I want to use filter to filter out all symbols 'x ;; I need a helper function ;; is-not-x? symbol -> boolean ;; the function returns false for 'x and true for any other symbol (define (is-not-x? a-sym) (not (symbol=? a-sym 'x)) ) (check-expect (filter is-not-x? (list 'x 'y 'z 'a 'x 'y)) (list 'y 'z 'a 'y)) ;; Now I need to filter out 'y ;; I need another helper function (define (is-not-y? a-sym) (not (symbol=? a-sym 'y)) ) (check-expect (filter is-not-y? (list 'x 'y 'z 'a 'x 'y)) (list 'x 'z 'a 'x)) ;; I would like a function that builds is-not-a-given-symbol? functions ;; symbol-comparison-builder: symbol -> (symbol -> boolean) ;; the function takes a symbol and returns a function symbol->boolean ;; that is true on all symbols except the given one (define (is-not-symbol-builder given-sym) ;; I define my function as local; it will have given-symbol built in (local ((define (is-not-sym? a-sym) (not (symbol=? a-sym given-sym)))) ;; return the newly-constructed function is-not-sym?) ) (define is-not-a? (is-not-symbol-builder 'a)) (check-expect (filter is-not-a? (list 'x 'y 'z 'a 'x 'y)) (list 'x 'y 'z 'x 'y)) (define is-not-z? (is-not-symbol-builder 'z)) (check-expect (filter is-not-z? (list 'x 'y 'z 'a 'x 'y)) (list 'x 'y 'a 'x 'y)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Now we write a function that makes more general functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Suppose I use map to square elements of (list 1 2 3): ;; square: number -> number ;; returns the square of a given number (define (square x) (* x x)) (check-expect (map square (list 1 2 3)) (list 1 4 9)) ;; Now I want to square elements of (2 3 4 5) (check-expect (map square (list 2 3 4 5 )) (list 4 9 16 25)) ;; What if I just wanted a function to square all elements ;; of any list of numbers? ;; We can use local to define functions that return functions ;; map-function-builder: (X -> Y) -> (listof X -> listof Y) ;; the function takes a function f from X to Y and returns a ;; function that applies f to each element of a list of X, ;; returning a list of Y (define (map-function-builder a-function) (local ((define (result-function a-list) (map a-function a-list))) result-function ) ) (define square-list (map-function-builder square)) (check-expect (square-list (list 1 2 3)) (list 1 4 9)) (check-expect (square-list (list 2 3 4 5)) (list 4 9 16 25)) ;; Our function is general: (define length-lists (map-function-builder length)) (check-expect (length-lists (list (list 1 2) (list 3 4 5) empty (list 6))) (list 2 3 0 1)) ;; define a function that produces foldr-like functions ;; that can be applied to various lists (define (foldr-function-builder a-function a-seed) (local ((define (result-function a-list) (foldr a-function a-seed a-list))) result-function)) (define sum-list (foldr-function-builder + 0)) (check-expect (sum-list (list 1 2 3)) 6) ;; These examples refer to Ch 24 (Intermezzo 4): defining functions ;; on the fly with lambda. ;; We will be using lambda more frequently than it is used in the book ;; It looks like we need 'local' for functions returning functions, ;; but actually there is another way. ;; Functions can be defined at any point in code using 'lambda' ;; This example creates a function and passes it to filter (check-expect (filter (lambda (a-sym) (not (symbol=? 'y a-sym))) (list 'x 'y 'z 'a 'x 'y)) (list 'x 'z 'a 'x)) ;; or as a "builder" function with no local: ;; map-function-builder1: (X -> Y) -> (listof X -> listof Y) ;; the function takes a function f from X to Y and returns a ;; function that applies f to each element of a list of X, ;; returning a list of Y (define (map-function-builder1 a-function) (lambda (a-list) (map a-function a-list)) ) (define square-list1 (map-function-builder1 square)) (check-expect (square-list1 (list 1 2 3)) (list 1 4 9)) (check-expect (square-list1 (list 2 3 4 5)) (list 4 9 16 25)) ;; define foldr-function-builder1 ;(define sum-list1 (foldr-function-builder1 + 0)) ;(check-expect (sum-list1 (list 1 2 3)) 6) ;; lambda is the internal way functions are defined in Scheme ;; For instance, the square function ;; (define (square x) (* x x)) ;; can equivalently be defined as (define square1 (lambda (x) (* x x))) ;; no parentheses before the function name! (check-expect (square1 2) 4)