Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8756001
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T13:58:04+00:00 2026-06-13T13:58:04+00:00

I was curious about defining multiple lexically scoped functions in Scheme that can call

  • 0

I was curious about defining multiple lexically scoped functions in Scheme that can call each other. Working in SICP, I produced the following function using block structure to solve Exercise 1.8 (calculating cube-root using Newton’s method):

(define (cbrt x)
  (define (good-enough? guess prev-guess)
    (< (/ (abs (- guess prev-guess))
          guess)
       0.001))
  (define (improve guess)
    (/ (+ (/ x (square guess))
          (* 2 guess))
       3))
  (define (cbrt-iter guess prev-guess)
    (if (good-enough? guess prev-guess)
        guess
        (cbrt-iter (improve guess)
                   guess)))
  (cbrt-iter 1.0 0.0))

This works fine, but it got me wondering how Scheme (and perhaps Common Lisp) might handle this same scenario using lexical scoping and the let form. I tried to implement it using let with the following kludgy code:

(define (cbrt x)
  (let ((calc-cbrt
         (lambda (guess prev-guess)
           (let ((good-enough?
                  (lambda (guess prev-guess)
                    (< (/ (abs (- guess prev-guess))
                          guess)
                       0.001))))
             (good-enough? guess prev-guess))
           (let ((improve
                  (lambda (guess)
                    (/ (+ (/ x (square guess))
                          (* 2 guess))
                       3))))
             (improve guess))
           (let ((cbrt-iter
                  (lambda (guess prev-guess)
                    (if (good-enough? guess prev-guess)
                        guess
                        (cbrt-iter (improve guess)
                                   guess)))))
             (cbrt-iter 1.0 0.0)))))
    (calc-cbrt 1.0 0.0)))

The problem that I see below is when cbrt-iter attempts to call the good-enough? procedure. Since the good-enough? procedure is only local to the scope of the first nested let block, cbrt-iter has no way to access it. It seems that this can be solved by nesting the cbrt-iter function within the enclosing let of good-enough, but this seems also very kludgy and awkward.

What is the define form doing that is different in this case? Is the define form expanding to lambda expressions instead of the “let over lambda” form (I recall something similar being done in the Little Schemer book using the form ((lambda (x) x x) (lambda (y) ...)), but I am not sure how this would work). Also, by way of comparison, how does Common Lisp handle this situation – is it possible to use lexically scoped defun‘s ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T13:58:06+00:00Added an answer on June 13, 2026 at 1:58 pm

    First of all, you don’t need to introduce a new procedure calc-cbrt – you could just call calc-iter instead.

    Second, the meaning of define and let are quite different. Define installs the definitions into the local scope, as in your example. However, let expressions are just syntactic sugar for lambda expressions (see SICP section 1.3 for details). As a result (and as you mention), variables declared via (let (<decl1> ...) <body>) are only visible inside <body>. So, your pattern of (let <decls1> <body1>) (let <decls2> <body2>) ... doesn’t work, since none of the definitions will “survive” to be seen in other scopes.

    So, we should write something like this:

    (define (cbrt x)
       (let ((good-enough? (lambda ...))
             (improve (lambda ...))
             (cbrt-iter (lambda ...)))
         (cbrt-iter 1.0 0.0)))
    

    Now, at least, the call to cbrt-iter can see the definition of cbrt-iter.

    But there’s still a problem. When we evaluate (cbrt-iter 1.0 0.0), we evaluate the body of cbrt-iter where guess and prev-guess take the values 1.0 and 0.0. But, in the body of cbrt-iter, the variables improve and good-enough? aren’t in scope.

    You might be tempted to use nested lets, which is often a good choice:

    (define (cbrt x)
       (let ((good-enough? (lambda ...))
             (improve (lambda ...)))
         (let ((cbrt-iter (lambda ...)))
           (cbrt-iter 1.0 0.0))))
    

    The problem is that cbrt-iter needs to call itself, but it’s not in scope until the body of the inner let!

    The solution here is to use letrec, which is like let but makes the new bindings visible inside all the declarations as well as the body:

    (define (cbrt x)
       (let ((good-enough? (lambda ...))
             (improve (lambda ...)))
         (letrec ((cbrt-iter (lambda ...)))
           (cbrt-iter 1.0 0.0))))
    

    We can even use letrec to create mutually recursive procedures, just as we could with define.

    Unfortunately, it would take me some time to explain how letrec and define actually work, but here’s the secret: they both use mutation internally to create circularity in the environment data structure, allowing recursion. (There is also a way to create recursion using only lambda, called the Y combinator, but it’s rather convoluted and inefficient.)

    Luckily, all these secrets will be revealed in Chapter 3 and Chapter 4!

    For another perspective, you might take a look at Brown University’s online PL class, which basically goes straight to this topic (although it omits define), but I find that SICP is better at forcing you to understand the sometimes complex environment structures that are created.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Curious about running multiple xvfb displays: I have between 10-50 instances of a script
I'm curious about the correct way to architect an application that consists of the
I am curious about COM+, DCOM. I know that MSFT does not encourage you
I'm curious about the possibility of having a .NET class library that provides a
I know that white space is irrelevant in JavaScript, but I am curious about
I'm just curious about whether or not I have to call this on the
I was curious about the __builtin__ module and how it's used, but I can't
I'm curious about best practice when it comes to updating a domain object that
I'm curious about using two APIs that both utilize OAuth2 authentication in the same
I was curious about how other people use the this keyword. I tend to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.