# 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`

and`g`

. Fill in the defintion for the combinator`fsub`

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 that`deriv`

is not a combinator, but rather returns a number. The forces us to add some`lambda`

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 like`fderiv`

. Fill in definition of`binop->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))
```