(import (rnrs))
(define (derive f dx)
(lambda (x)
(/ (- (f (+ x dx))
(f x))
dx)))
(define (make-improver f dx)
(let ((df (derive f dx)))
(lambda (guess)
(- guess
(/ (f guess)
(df guess))))))
(define (make-good-enough f tolerance)
(lambda (guess)
(< (abs (f guess))
tolerance)))
(define (iterative-improve x improve good?)
(if (good? x)
x
(iterative-improve (improve x)
improve
good?)))
(define (solve f guess dx tolerance)
(iterative-improve guess
(make-improver f dx)
(make-good-enough f tolerance)))
(define (solve-it f y dx tolerance)
(solve (lambda (x)
(- (f x) y))
1.0
dx
tolerance))
(define (inverse f dx tolerance)
(lambda (y)
(solve-it f y dx tolerance)))
(define (println . msgs)
(for-each display msgs)
(newline))
(define-syntax spy
(syntax-rules ()
((_ expr)
(let ((result expr))
(println (quote expr) " => " result)
result))))
(define (test-it)
(let* ((dx 0.00001)
(tolerance 0.001))
(let* ((double (lambda (x) (* 2 x)))
(halve (inverse double dx tolerance)))
(spy (double 3))
(spy (halve 10)))
(println)
(let* ((cube (lambda (x) (* x x x)))
(cube-root (inverse cube dx tolerance)))
(spy (cube 3))
(spy (cube-root 64)))
(println)
(let* ((quad (lambda (x)
(+ (* x x)
(* 3 x)
5)))
(unquad (inverse quad dx tolerance)))
(spy (quad 7))
(spy (unquad 75)))
(println)))
(double 3) => 6
(halve 10) => 4.999999999973795
(cube 3) => 27
(cube-root 64) => 4.000017469904781
(quad 7) => 75
(unquad 75) => 7.000000064702703