ellie0414
ellie0414

Reputation: 81

Recursion (or while loops) in Scheme

(define (orderedTriples n)
(set! i n)
(set! j n)
(set! k n)
(while (>= i 0)
   (while (>= j 0)
     (while (>= k 0)
       (printf "(~a, ~a, ~a)" i j k) 
       (set! k (- k 1))) 
     (set! j (- j 1))) 
  (set! i (- i 1))))

So my issue is...I am confused as to how to make while loops work in scheme (I'm very new to this so excuse the syntax if I am WAY off). I typed while into here just for the purpose of working through a problem and to show what I am trying to accomplish. Could anyone help me with a simple recursion example or nested recursion?

Upvotes: 3

Views: 19870

Answers (3)

Terje D.
Terje D.

Reputation: 6315

You can use the do loop, which is written like this (for the inner loop of your function):

(do ((k n (- k 1)))               ; variable, initialization, and updating form
   ((< k 0))                      ; stop condition, and optionally return value
  (printf "(~a, ~a, ~a)" i j k))  ; body forms

See http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_idx_138 for further information on the do iteration construct.

Upvotes: 3

to_the_crux
to_the_crux

Reputation: 267

If you had to, you could do this with recursion.

(define (ordered-triples n)
  (let iloop ((i n))
    (unless (negative? i)
      (let jloop ((j n))
        (unless (negative? j)
          (let kloop ((k n))
            (unless (negative? k)
              (printf "~a ~a ~a\n" i j k)
              (kloop (sub1 k))))
          (jloop (sub1 j))))
      (iloop (sub1 i)))))

Of course, it's easier to use Racket's for* loop.

Upvotes: 1

&#211;scar L&#243;pez
&#211;scar L&#243;pez

Reputation: 235994

Depending on the Scheme interpreter in use, there are several ways to implement the required loops. For example, in Racket it's as simple as using iterations and comprehensions:

(define (orderedTriples n)
  (for* ([i (in-range n -1 -1)]
         [j (in-range n -1 -1)]
         [k (in-range n -1 -1)])
    (printf "(~a, ~a, ~a)" i j k)))

The style of programming shown in the question (assuming it worked) is heavily discouraged in Scheme - using mutation (the set! operation) for looping is a big no-no, that's how you'd solve the problem in a C-like language, but in Scheme in particular (and in Lisp in general) there are other constructs for implementing iteration in a program (the solution given by @TerjeD demonstrates the use of do, for instance), and even if such constructs didn't exist, a recursive solution or a solution using higher-order procedures would be preferred. For example, here's another possible solution, using nested mappings with only standard procedures (with the exception of printf, which is non-standard):

(define (range n)
  (if (negative? n)
      '()
      (cons n (range (- n 1)))))

(define (orderedTriples n)
  (for-each (lambda (i)
              (for-each (lambda (j)
                          (for-each (lambda (k)
                                      (printf "(~a, ~a, ~a)" i j k))
                                    (range n)))
                        (range n)))
            (range n)))

Upvotes: 6

Related Questions