I am following the SICP lectures from MIT, and this is what I tried to find the square root approximation of a number by Heron of Alexandria's method. This is my first time trying out lisp, sorry for making noobie mistakes.
(define guess 1)
(define (avg a b)
(/ (+ a b) 2))
(define (try guess x)
(if (goodEnough guess x)
guess
(improve guess x)))
(define (improve guess x)
(define guess (avg guess (/ x guess)))
(try guess x)
)
(define (goodEnough guess x)
(= guess (avg guess (/ x guess))))
(print (try 1 25))
I am using Chicken scheme compiler to print this. This is the output:
Error: (/) bad argument type: #<unspecified>
Call history:
1.a.SquareRootApproximation.scm:29: try
1.a.SquareRootApproximation.scm:17: goodEnough
1.a.SquareRootApproximation.scm:27: avg
1.a.SquareRootApproximation.scm:19: improve <--
Updated: I have changed my approach towards this problem using lisp with more abstraction, yet I can't figure out what this new error wants to imply. Any fixes? Thanks!
The value
#<unspecified>
is basically "void" in other languages. It is used as a return value whenever some procedure has nothing useful to return (for example,print
will return this). It is also in some situations used as a temporary placeholder value, for example when handling an innerdefine
.Normally this temporary placeholder should not be visible to the user of the language, but it appears you've hit a strange edge case in the language (congratulations! This happens rarely). The error happens because
(define guess (avg guess (/ x guess)))
in theimprove
procedure is simultaneously defining a variable and using that variable. The behaviour of doing this is not well-specified, and some Scheme implementations will do what CHICKEN is doing (Guile, Gauche, Gambit) whereas others will give a somewhat more meaningful error message (MIT, Scheme48, Racket). The reason this is ill-specified has to do with the fact that innerdefine
expands toletrec
, because it allows mutually recursive procedures to be defined, but that creates a bit of an issue: what should happen for(define a b) (define b a)
, for example?Your intention seems to be using the old guess variable that's passed as input to the procedure, so instead of using
define
you could uselet
to bind a new value forguess
(how this should behave is well-specified), or just use a different name for it, likenew-guess
.