At Fri, 14 Sep 2012 15:30:22 -0400, Eli Barzilay wrote: > Four hours ago, Matthew Flatt wrote: > > > > Also, I think the names `#:while' and `#:until' are too close to > > `#:when' and `#:unless'. I suggest `#:break-when' and `#:break-unless'. > > Compare: > > > > > (for*/list ([j 2] [i 10] #:when (i . < . 5)) i) > > '(0 1 2 3 4 0 1 2 3 4) > > > (for*/list ([j 2] [i 10] #:break-unless (i . < . 5)) i) > > '(0 1 2 3 4) > > > > I imagine that `#:break-when' and `#:break-unless' are allowed among > > the clauses much like `#:when' and `#:unless', but also allowed at the > > end of the body. Is that what you had in mind? > > Sorry for the bike-shedding, but to me that `#:break-unless' is even > harder to read than `#:until'. Possible explanation: "break unless" > makes me parse two words and figure out how they combine, and "while" > is something that I know without doing so.
After trying out various options, I agree that `break-when' is too many words. I'm currently trying just `break' and dropping `break-unless', and that feels better. At Fri, 14 Sep 2012 11:49:20 -0400, Carl Eastlund wrote: > I agree that #:while and #:until are easily confused with #:when and > #:unless. I slightly prefer #:stop- to #:break- as a prefix here, it seems > a more natural word. I like "break" because it goes with "for", it avoids potential confusion with "stop" in `stop-after' and `stop-before', and it is more clearly different from "final" (which is used below). > I like the idea of allowing these clauses at the end > of the body to give a notion of stopping after the current iteration. It turns out that allowing `#:break' at the very end of the body causes problems with scope and composition. Imagine trying to implement `for/set' by wrapping its body in an expansion to `for/fold'. Maybe you can look from the end of the body and skip back over `#:break' clauses, but now imagine that the last form before `break' expands to a combination of a definition and an expression, and the `#:break' clause wants to refer to the identifier that is bound in the expansion. We could probably make all that work with `local-expand' and internal-definition contexts, but that gets complicated. Requiring an expression at the end of a `for' body --- while allowing `#:break' clauses otherwise interspersed in the body --- avoids composition and scope problems. Macros still have to do a little work to juggle `#:break' clauses, but a `split-for-body' helper function is straightforward to use. Meanwhile, to support breaking after the current element, I'm trying out `#:final'. A `#:final' clause is like `#:break', except that it ends the loop after the next run of the body. (The two kinds of clauses closely related to `stop-before' and `stop-after'.) > (for/list ([i 10]) #:break (= i 2) i) '(0 1) > (for/list ([i 10]) #:final (= i 2) i) '(0 1 2) > (for ([book '("Guide" "Story" "Reference")] #:break (equal? book "Story") [chapter '("Intro" "Details" "Conclusion")]) (printf "~a ~a\n" book chapter)) Guide Intro Guide Details Guide Conclusion > (for* ([book '("Guide" "Story" "Reference")] [chapter '("Intro" "Details" "Conclusion")]) #:break (and (equal? book "Story") (equal? chapter "Conclusion")) (printf "~a ~a\n" book chapter)) Guide Intro Guide Details Guide Conclusion Story Intro Story Details > (for* ([book '("Guide" "Story" "Reference")] [chapter '("Intro" "Details" "Conclusion")]) #:final (and (equal? book "Story") (equal? chapter "Conclusion")) (printf "~a ~a\n" book chapter)) Guide Intro Guide Details Guide Conclusion Story Intro Story Details Story Conclusion > (for ([book '("Guide" "Story" "Reference")] #:final (equal? book "Story") [chapter '("Intro" "Details" "Conclusion")]) (printf "~a ~a\n" book chapter)) Guide Intro Guide Details Guide Conclusion Story Intro _________________________ Racket Developers list: http://lists.racket-lang.org/dev