tags:

views:

96

answers:

2

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!

+4  A: 

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).

Greg Harman
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
That makes sense, but why the imbalance? [( to open and ] to close...
Greg Harman
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
@Greg Harman: I see the imbalance was corrected in the original question before I read it. I assume that was just a typo.
Greg Hewgill
@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.
Greg Harman
+3  A: 

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 if 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.

Jörn Horstmann