0

I would like to see how the value of a square root is iteratively improved. For example on the following:

#lang sicp
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)

It gets values such as the following:

1 1
2 1.5
3 1.4166666666666665
4 1.4142156862745097

As an example of what I want to show, in Javascript I would do something like:

const sqrt_iter = (guess, x) => {
    console.log(count++, guess);
    return good_enough(guess, x) ? guess : sqrt_iter(improve(guess, x), x);
}
const sqrt = x => sqrt_iter(1.0, x);

How could I print or trace these intermediate values in DrRacket/SICP? I tried doing (trace sqrt) but it said not found.

David542
  • 104,438
  • 178
  • 489
  • 842

3 Answers3

2

I am sure Racket has some fancy trace facility. But there's a famous quote (due I think to John Foderaro):

Lisp [for which read Racket] is the programmable programming language.

What this means is: if there's no tracing facility, or you are too lazy to make one, you can just write one.

Here is a rudimentary one I wrote in five minutes:

#lang racket

(provide define/traced)

(define trace-depths (make-parameter 0))

(define (spaces n)
  (make-string n #\ ))

(define-syntax define/traced
  (syntax-rules ()
    [(_ (name arg ...) form ...)
     (define/traced name (λ (arg ...) form ...))]
    [(_ (name . args) form ...)
     (define/traced name (λ args form ...))]
    [(_ name function)
     (define name
       (λ args
         (let* ([depth (trace-depths)]
                [prefix (spaces depth)])
           (parameterize ([trace-depths (+ depth 1)])
             (printf "~A~S ...~%" prefix `(,'name ,@args))
             (call-with-values
              (thunk (apply function args))
              (λ results
                (printf "~A-> ~S~%" prefix results)
               (apply values results)))))))]))

Stash this in a file called define-traced.rkt and then require it, and tell it to trace the procedures you care about:

#lang racket

(require "define-traced.rkt")

(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define/traced (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define/traced (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)

Which will duly print this:

(sqrt-iter 1.0 2) ...
 (improve 1.0 2) ...
 -> (1.5)
 (sqrt-iter 1.5 2) ...
  (improve 1.5 2) ...
  -> (1.4166666666666665)
  (sqrt-iter 1.4166666666666665 2) ...
   (improve 1.4166666666666665 2) ...
   -> (1.4142156862745097)
   (sqrt-iter 1.4142156862745097 2) ...
   -> (1.4142156862745097)
  -> (1.4142156862745097)
 -> (1.4142156862745097)
-> (1.4142156862745097)
1.4142156862745097

Note that when I said it was a rudimentary facility I meant it: in particular it will probably turn tail calls into non-tail calls, and there are many other things wrong with it. But it took less long to write than it would take to read the manual on some hairy facility. If I was going to use this thing just once (and this is probably the only time I will ever use it: it only made it into a file so I could require it in another file) it's worth it. This is one of the glories of Lisp-family languages.

ignis volens
  • 7,040
  • 2
  • 12
2

Try begin with printf (and also add one variable as counter):

#lang racket

(define (square x)
  (* x x))

(define (average x y)
  (/ (+ x y) 2))

(define (improve guess x)
  (average guess (/ x guess)))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001 ))

(define (sqrt-iter guess x count)
  (begin
    (printf "~a ~a \n" count guess)
    (if (good-enough? guess x)
        guess
        (sqrt-iter (improve guess x)
                   x
                   (+ 1 count)))))

(define (sqrt x) (sqrt-iter 1.0 x 1))
(sqrt 2)
1 1.0 
2 1.5 
3 1.4166666666666665 
4 1.4142156862745097

1.4142156862745097

Note that I used #lang racket- it seems that sicp don't have print or printf, but you can try write or display to achieve similar result.

Martin Půda
  • 7,353
  • 2
  • 6
  • 13
  • 2
    you can drop `begin` and the program is identical. the body of a `define` procedure already supports evaluating multiple expressions and implicitly returns the last one. – Mulan May 10 '22 at 12:48
1

@ignis provides the proper technique for this. However, before you dive into the deep ocean of define-syntax, maybe you want the quick-and-dirty approach -

#lang sicp

(define (sqrt-iter guess x)
  (for-each display (list "sqrt-iter" " " guess " " x "\n"))
  (if (good-enough? guess x)
      guess
      (sqrt-iter (improve guess x) x)))

(sqrt 2)
sqrt-iter 1.0 2
sqrt-iter 1.5 2
sqrt-iter 1.4166666666666665 2
sqrt-iter 1.4142156862745097 2
1.4142156862745097
Mulan
  • 129,518
  • 31
  • 228
  • 259