9

What is the difference between CODE SNIPPET 1 and CODE SNIPPET 2?

;CODE SNIPPET 1
(define i 0)                      
(do ()                             
  ((= i 5))                       ; Two sets of parentheses
  (display i)                     
  (set! i (+ i 1))) 


;CODE SNIPPET 2
(define i 0)                      
(do ()                             
  (= i 5)                         ; One set of parentheses
  (display i)                     
  (set! i (+ i 1))) 

The first code snippet produces 01234 and the second produces 5. What is going on? What does the extra set of parentheses do? Also, I have seen [(= i 50)] used instead of ((= i 5)). Is there a distinction? Thanks!

David Jones
  • 4,766
  • 3
  • 32
  • 45
Gautam
  • 1,732
  • 4
  • 18
  • 26
  • 2
    What do you mean by "produces"? The first snippet *prints* "01234" and *evaluates* to nothing. The second snippet doesn't *print* anything, and *evaluates* to 5. – newacct Jul 08 '10 at 03:06

2 Answers2

17

The general structure of a do form is like this:

(do ((<variable1> <init1> <step1>)
     ...)
    (<test> <expression> ...)
  <command> ...)

Paraphrasing http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-6.html#node_chap_5, each iteration begins by evaluating <test>, if it evaluates to a true value, <expression>s are evaluated from left to right and the last value is returned as the result of the do form. In your second example = would be evaluated as a boolean meaning true, then i would be evaluated and at last 5 is the return value of the form. In the first case (= i 5) is the test and the do form returns an undefined value. The usual way to write a loop would be more like this:

(do ((i 0 (+ i 1)))
    ((= i 5) i)      ; maybe return the last value of the iteration
  (display i))

You don't need an explicit mutation of the loop variable as this is handled by the <step> expression.

metatron
  • 896
  • 7
  • 14
Jörn Horstmann
  • 33,639
  • 11
  • 75
  • 118
6

In the first case, ((= i 5)) functions as a test for termination. So the do loop is repeated until i = 5.

In the second case, (= i 5) isn't a test. The do loop simply executes the first form, which returns 5.

--

(Per the attached comments) brackets are interchangeable in some dialects of scheme. It is sometimes considered idiomatic to use [] for parameters (i.e. to the parent do).

G__
  • 7,003
  • 5
  • 36
  • 54
  • 2
    Some dialects of Scheme allow `[]` as well as `()` to mean the same thing. The distinction is just to enhance the visual difference between the groups. – Greg Hewgill Jul 07 '10 at 22:20
  • In particular, the very popular Racket/mzscheme dialect allows any set of paired brackets to be used interchangeably, so for example `{= [+ 1 2] (- 7 4)}` returns `#t`. The imbalance was surely a typo. I've noticed a tendency to use square brackets for special "syntactic" lists like the one in question. – Chuck Jul 07 '10 at 22:27
  • Harman: I see the imbalance was corrected in the original question before I read it. I assume that was just a typo. – Greg Hewgill Jul 07 '10 at 22:35
  • @newacct You are correct; for some reason I mentally parsed = as an assignment operator, and the do evaluating all forms rather than just the first one. Have updated my answer accordingly. – G__ Jul 08 '10 at 03:40
  • um, no. the `do` loop does not "simply execute" the second form. What does that even mean?? – Will Ness Dec 12 '19 at 11:45