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.rkt
with 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
f
andg
. Fill in the defintion for the combinatorfsub
so 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
fsub
for plotting reveals a flaw; namely thatderiv
is not a combinator, but rather returns a number. The forces us to add somelambda
boilerplate.
(plot (function (fsub (lambda (x) (deriv sin x)) cos) -2pi 2pi))
- We can abstract away some more boilerplate and define a function
fderiv
which 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->fbinop
below.
(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))