简体   繁体   中英

Scheme: recursive zeno function

The following is a function that sums 1/2^n until it reaches 0 . Can someone tell me whether or not I need an else statement, and how to arrange my parenthesis so there are no compile errors?

(define (zeno n)
  (if (= n 0)
      (+ 0)
      (else
        ((+ (/ 1 (expt 2 n )))
         ((zeno(- n 1)))))))

I have my hat, my tea, and nothing to do for a while at work. You know what time it is.

[dons code-review hat]

Firstly, if you had properly indented your code, it would read

(define (zeno n)
    (if (= n 0)
        (+ 0)
        (else
         ((+ (/ 1 (expt 2 n)))
          ((zeno (- n 1)))))))

if in Scheme is not like the if / then / else construct of C-like languages. It's actually the ternary operator . In other words, else makes no sense in this context.

(define (zeno n)
    (if (= n 0)
        (+ 0)
        ((+ (/ 1 (expt 2 n)))
         ((zeno (- n 1)))))))

You don't need to use + to return a number; numbers are self-evaluating.

(define (zeno n)
    (if (= n 0)
        0
        ((+ (/ 1 (expt 2 n)))
         ((zeno (- n 1)))))))

When you have an expression like (foo bar baz) , it usually means

"Call the function foo with arguments bar and baz "

You can't just add extra parentheses as you please; those change the meaning of the expression. For example, ((foo) (bar baz)) means

"Call the function foo with no arguments, and call its result with the result of calling bar with the argument baz "

In other words,

...
((+ (/ 1 (expt 2 n)))
 ((zeno (- n 1))))))

what you're saying, and almost certainly don't mean, here is

"Call the function (+ (/ 1 (expt 2 n))) with the result of calling the result of calling zeno with the argument (- n 1) with no arguments."

What you seem to mean is

"Add 1 divided by 2^n to the result of calling zeno with one less than n "

Which means that what you should say is

(define (zeno n)
    (if (= n 0)
        0
        (+ (/ 1 (expt 2 n))
           (zeno (- n 1)))))

You have a couple of syntax errors (erroneous parenthesis, mostly), and the if form doesn't use else - don't get me wrong, it does have an "else" part, it's just that you must not explicitly write else for it to work. I believe this is what you were aiming for:

(define (zeno n)
  (if (= n 0)
      0
      (+ (/ 1 (expt 2 n))
         (zeno (- n 1)))))

For a completely different approach, this uses an explicit do loop to do the summing. It avoids using expt (by design).

(define (zeno n)
  (do ((n n (- n 1))
       (sum 0 (+ sum frac))
       (frac 1/2 (/ frac 2)))
      ((zero? n) sum)))

It may or may not be more readable when written into its equivalent named let form:

(define (zeno n)
  (let loop ((n n)
             (sum 0)
             (frac 1/2))
    (if (zero? n)
        sum
        (loop (- n 1) (+ sum frac) (/ frac 2)))))

For an even more completely different approach, you can use SRFI 41 streams:

(define zeno
  (let ((frac-stream (stream-iterate (cut / <> 2) 1/2)))
    (lambda (n)
      (stream-fold + 0 (stream-take n frac-stream)))))

(The above snippet also requires SRFI 26 to be loaded, in addition to SRFI 41.)


An even even more completely different approach: just use the closed-form solution! (Thanks, WorBlux.)

(define (zeno n)
  (- 1 (/ (expt 2 n))))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM