You are not logged in.
I'm working through Structure and Interpretation of Computer Programs, and I've run into some behaviour I don't understand.
The code:
(define (average x y)
(/ (+ x y) 2))
(define (refine r g)
(print "["r"]["g"]")
(average (/ r g) g))
(define (sqrt-guess rad guess)
(define oldguess guess)
(define guess (refine rad guess)) # problem line
(if (= oldguess guess)
guess
(sqrt-guess rad guess)))
It seems that when refine is called in the problem line the second argument is not being 'received' as I would expect.
#;1> (sqrt-guess 9 1)
[9][#<unspecified>]
Error: (/) bad argument type: #<unspecified>
Call history:
<syntax> (sqrt-guess 9 1)
<eval> (sqrt-guess 9 1)
<eval> [sqrt-guess] (refine r g)
<eval> [refine] (print "[" r "][" g "]")
<eval> [refine] (average (/ r g) g)
<eval> [refine] (/ r g) <--
I tried (define guess (refine rad oldguess)), same outcome. At this point, I figure it's some consequence of applicative-order processing that I don't understand. But things got more interesting when I added a standalone call to refine:
(define (sqrt-guess rad guess)
(define oldguess guess)
(refine rad oldguess) # new line
(define guess (refine rad oldguess)) # (define guess (refine rad guess)) also works
(if (= oldguess guess)
guess
(sqrt-guess rad guess)))
Now the code runs as expected and returns an answer. However, if I change "oldguess" to "guess" in the first refine line:
(define (sqrt-guess rad guess)
(define oldguess guess)
(refine rad guess)
(define guess (refine rad oldguess)) # (define guess (refine rad guess)) also fails
(if (= oldguess guess)
guess
(sqrt-guess rad guess)))
the original error re-occurrs. In every case the 'standalone' call to refine gets both arguments as expected; it's the one in "define guess" that has issues.
I'm not looking for help fixing the code, but for an explanation/breakdown of what's going on. Thanks.
Last edited by alphaniner (2013-06-20 13:20:34)
But whether the Constitution really be one thing, or another, this much is certain - that it has either authorized such a government as we have had, or has been powerless to prevent it. In either case, it is unfit to exist.
-Lysander Spooner
Offline
I don't know much about Scheme, but I believe that redefining 'guess' is confusing the compiler. I do know that guess isn't seen as a number by the time that the function runs; maybe a reference to a function?
You are working too hard though. Defining guess and oldguess can be reduced to one let function:
(define (sqrt-guess rad guess)
(let ((newguess (refine rad guess)))
(if (= guess newguess)
newguess
(sqrt-guess rad newguess))))
I don't know if this is the best let form in this situation, but it's cleaner.
*** Edit to fix the indentation of the if block. In a world full of parenthesis, one needs their indentation. ***
Last edited by skottish (2013-06-20 18:23:47)
Offline
I believe that redefining 'guess' is confusing the compiler.
You're right. That was my first thought too, but I swear I tried something like (define foo (refine rad guess)) which didn't work either. I just tried it again and it works just fine.
I haven't been introduced to let yet, and the way it's parenthesized I don't really understand how it works. I think of let in bash terms (ie. let x++) so maybe that's my problem. Anyway, I'll wait 'till I come across it in the text.
Using your suggestions I got it to work using only stuff I know:
(define (sqrt-guess rad guess)
(define newguess (refine rad guess))
(if (= newguess guess)
guess
(sqrt-guess rad newguess)))
Definitely cleaner. Thanks!
But whether the Constitution really be one thing, or another, this much is certain - that it has either authorized such a government as we have had, or has been powerless to prevent it. In either case, it is unfit to exist.
-Lysander Spooner
Offline