Using "do" in Scheme
Asked Answered
V

2

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!

Vallee answered 7/7, 2010 at 21:57 Comment(1)
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.Narra
B
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.

Biotin answered 7/7, 2010 at 23:8 Comment(0)
C
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).

Ciro answered 7/7, 2010 at 22:18 Comment(5)
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.Antitrust
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.Layer
Harman: I see the imbalance was corrected in the original question before I read it. I assume that was just a typo.Antitrust
@Narra 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.Ciro
um, no. the do loop does not "simply execute" the second form. What does that even mean??Cravat

© 2022 - 2024 — McMap. All rights reserved.