Combinators
We already know about higher order functions, functions which take other functions as arguments. Certain higher order functions return other functions; these are sometimes called combinators, especially when the "combine" two or more functions.
- download calculus.rkt and save it as
calculus.rkt - start a new file
plot-example.rktwith the following
#lang racket
(require plot)
(require "calculus.rkt")
- Suppose we want to make lots of plots comparing two functions (e.g. to see how closely they match). The core of one solution to the previous part looks like
(plot
(function
(lambda (x) (- (deriv sin x) (cos x))))
#:x-min -2pi
#:x-max 2pi)
- In order to promote code re-use, abstract out the two numerical functions of x, call them
fandg. Fill in the defintion for the combinatorfsubso that the given tests pass.
(define (fsub f g)
(lambda (x) ( ))
(module+ test
(require rackunit)
(define (sin2 x) (integrate cos x))
(define (cos2 x) (deriv sin x))
(define epsilon 0.001)
(define test-points (build-list 20 (lambda (x) (* 2 pi (random)))))
(for ([x test-points])
(check-= ((fsub cos cos2) x) 0 epsilon)
(check-= ((fsub sin sin2) x) 0 epsilon)))
- A first attempt attempt to use
fsubfor plotting reveals a flaw; namely thatderivis not a combinator, but rather returns a number. The forces us to add somelambdaboilerplate.
(plot (function (fsub (lambda (x) (deriv sin x)) cos) -2pi 2pi))
- We can abstract away some more boilerplate and define a function
fderivwhich is a combinator.
(define (fderiv f)
(lambda (x) (deriv f x)))
(plot (function (fsub (fderiv sin) cos) -2pi 2pi))
This last expression
(fsub (fderiv sin) cos)is sometimes called point-free style.If we think a bit about the function
fsub, the role of-is easy to abstract: it's just a function with two arguments. So we can define a function "factory" that makes combinators likefderiv. Fill in definition ofbinop->fbinopbelow.
(define (binop->fbinop op)
(lambda (f g)
(lambda (x) )))
(define fsub2 (binop->fbinop -))
(plot (function (fsub2 (fderiv sin) cos) -2pi 2pi)))
(define fadd (binop->fbinop +))
(plot (function (fadd sin cos) -2pi 2pi))