问题
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!
回答1:
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.
回答2:
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).
来源:https://stackoverflow.com/questions/3199228/using-do-in-scheme