<div dir="ltr">On Fri, Sep 6, 2013 at 2:58 PM, Stephen Chang <span dir="ltr"><<a href="mailto:stchang@ccs.neu.edu" target="_blank">stchang@ccs.neu.edu</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>> It's useful when the condition for loop termination and the value of the<br>
> loop body both depend on some derived computation from the sequence<br>
> elements:<br>
><br>
> (for/list ([x (in-stream S)])<br>
> (define y (f x))<br>
> #:break (g? y)<br>
> (h y))<br>
<br>
</div>Ok I see, thanks. It does make things easier to read when the break<br>
expression becomes too large to fit on one line. So is the reason why<br>
#:when and #:unless can't be used the same way because there already<br>
exist when and unless forms?<br></blockquote><div><br></div><div>Are you looking for an equivalent of C's "continue" statement? I could imagine clauses for skipping to the next iteration using the keyword #:continue or #:next, though I have no idea if the existing loop architecture would easily accommodate them. I don't think calling them #:when or #:unless makes sense outside the for clauses.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div>>> > Carl Eastlund<br>
>> ><br>
>> ><br>
>> > On Fri, Sep 6, 2013 at 2:31 PM, Stephen Chang <<a href="mailto:stchang@ccs.neu.edu" target="_blank">stchang@ccs.neu.edu</a>><br>
>> > wrote:<br>
>> >><br>
>> >> > "Among the bodys, besides stopping the iteration and preventing later<br>
>> >> > body evaluations, a #:break guard-expr or #:final guard-expr clause<br>
>> >> > starts a<br>
>> >> > new internal-definition context."<br>
>> >><br>
>> >> I had the same thought process as Carl. I now understand the behavior<br>
>> >> but I don't understand why it's needed? It seems kind of arbitrary<br>
>> >> since no other form allows multiple internal def contexts in the body<br>
>> >> like this. Is there a practical example?<br>
>> >><br>
>> >> On Fri, Sep 6, 2013 at 12:58 PM, Carl Eastlund <<a href="mailto:cce@ccs.neu.edu" target="_blank">cce@ccs.neu.edu</a>> wrote:<br>
>> >> > Okay, I see what's going on here. It's very subtle though, and<br>
>> >> > probably<br>
>> >> > deserves some explanation in split-for-body's documentation.<br>
>> >> ><br>
>> >> > My first thought on seeing my non-fix version break here is that I<br>
>> >> > can<br>
>> >> > make<br>
>> >> > split-for-body break the same way. The problem is that my non-fix<br>
>> >> > separates<br>
>> >> > the definition of fish? from the definitions of red? and blue?, which<br>
>> >> > it<br>
>> >> > depends on. I can make split-for-body separate them the same way, by<br>
>> >> > putting a #:break or #:final clause in between the definition of<br>
>> >> > fish?<br>
>> >> > and<br>
>> >> > the begin form.<br>
>> >> ><br>
>> >> > The problem with doing so is a subtle point about for loops that is<br>
>> >> > only<br>
>> >> > mentioned in the last sentence of the last paragraph of the<br>
>> >> > documentation of<br>
>> >> > for itself:<br>
>> >> ><br>
>> >> > "Among the bodys, besides stopping the iteration and preventing<br>
>> >> > later<br>
>> >> > body<br>
>> >> > evaluations, a #:break guard-expr or #:final guard-expr clause starts<br>
>> >> > a<br>
>> >> > new<br>
>> >> > internal-definition context."<br>
>> >> ><br>
>> >> > So that's what split-for-body is preserving, the boundaries between<br>
>> >> > internal<br>
>> >> > definition contexts. That's not at all what I had expected it was<br>
>> >> > doing; I<br>
>> >> > had no idea the body of a for loop constituted multiple such<br>
>> >> > contexts.<br>
>> >> ><br>
>> >> > Anyway, thanks for the clarification, I now understand why<br>
>> >> > abstractions<br>
>> >> > over<br>
>> >> > for loops need to use split-for-body.<br>
>> >> ><br>
>> >> > Carl Eastlund<br>
>> >> ><br>
>> >> ><br>
>> >> > On Fri, Sep 6, 2013 at 12:38 PM, Matthew Flatt <<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>><br>
>> >> > wrote:<br>
>> >> >><br>
>> >> >> Sorry that I forgot to add the `let` while turning the code you sent<br>
>> >> >> into a full example. Here's another try.<br>
>> >> >><br>
>> >> >> #lang racket/base<br>
>> >> >> (require (for-syntax racket/base<br>
>> >> >> syntax/parse<br>
>> >> >> syntax/for-body))<br>
>> >> >><br>
>> >> >> (define-syntax (for/print/good stx)<br>
>> >> >> (syntax-parse stx<br>
>> >> >> [(_ clauses . body)<br>
>> >> >> (with-syntax ([([pre ...] [post ...]) (split-for-body stx<br>
>> >> >> #'body)])<br>
>> >> >> (syntax<br>
>> >> >> (for clauses<br>
>> >> >> pre ...<br>
>> >> >> (printf "~v\n" (let () post ...)))))]))<br>
>> >> >><br>
>> >> >> (define-syntax-rule (for/print/fixed/not clauses pre ... result)<br>
>> >> >> (for clauses<br>
>> >> >> pre ...<br>
>> >> >> (printf "~v\n" (let () result))))<br>
>> >> >><br>
>> >> >> (for/print/fixed/not ([i 1])<br>
>> >> >> (define (fish? v) (or (red? v) (blue? v)))<br>
>> >> >> (begin<br>
>> >> >> (define (red? v) (eq? v 'red))<br>
>> >> >> (define (blue? v) (eq? v 'blue))<br>
>> >> >> (fish? i)))<br>
>> >> >><br>
>> >> >> At Fri, 6 Sep 2013 12:30:17 -0400, Carl Eastlund wrote:<br>
>> >> >> > You're proving that (let () ...) is necessary, which I have<br>
>> >> >> > explicitly<br>
>> >> >> > agreed with since the original email, but you have not yet<br>
>> >> >> > demonstrated<br>
>> >> >> > that split-for-body is necessary. Here is the fix I have<br>
>> >> >> > described<br>
>> >> >> > twice<br>
>> >> >> > already, now explicitly put into the define-syntax-rule solution:<br>
>> >> >> ><br>
>> >> >> > (define-syntax-rule (for/print/fixed clauses pre .. result)<br>
>> >> >> > (for clauses<br>
>> >> >> > pre ...<br>
>> >> >> > (printf "~v\n" (let () result))))<br>
>> >> >> ><br>
>> >> >> > Carl Eastlund<br>
>> >> >> ><br>
>> >> >> ><br>
>> >> >> > On Fri, Sep 6, 2013 at 12:25 PM, Matthew Flatt<br>
>> >> >> > <<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>><br>
>> >> >> > wrote:<br>
>> >> >> ><br>
>> >> >> > ><br>
>> >> >> > > #lang racket/base<br>
>> >> >> > > (require (for-syntax racket/base<br>
>> >> >> > > syntax/parse<br>
>> >> >> > > syntax/for-body))<br>
>> >> >> > ><br>
>> >> >> > > (define-syntax (for/print/good stx)<br>
>> >> >> > > (syntax-parse stx<br>
>> >> >> > > [(_ clauses . body)<br>
>> >> >> > > (with-syntax ([([pre ...] [post ...]) (split-for-body stx<br>
>> >> >> > > #'body)])<br>
>> >> >> > > (syntax<br>
>> >> >> > > (for clauses<br>
>> >> >> > > pre ...<br>
>> >> >> > > (printf "~v\n" (let () post ...)))))]))<br>
>> >> >> > ><br>
>> >> >> > > (define-syntax-rule (for/print/bad clauses pre ... result)<br>
>> >> >> > > (for clauses<br>
>> >> >> > > pre ...<br>
>> >> >> > > (printf "~v\n" result)))<br>
>> >> >> > ><br>
>> >> >> > > ;; Try changing to for/print/bad:<br>
>> >> >> > > (for/print/good ([i 1])<br>
>> >> >> > > (define (fish? v) (or (red? v) (blue? v)))<br>
>> >> >> > > (begin<br>
>> >> >> > > (define (red? v) (eq? v 'red))<br>
>> >> >> > > (define (blue? v) (eq? v 'blue))<br>
>> >> >> > > (fish? i)))<br>
>> >> >> > ><br>
>> >> >> > ><br>
>> >> >> > > At Fri, 6 Sep 2013 12:17:56 -0400, Carl Eastlund wrote:<br>
>> >> >> > > > Right, that's the issue with needing the (let () result) in my<br>
>> >> >> > > > define-syntax-rule version. I still didn't need<br>
>> >> >> > > > split-for-body,<br>
>> >> >> > > > which<br>
>> >> >> > > > doesn't guarantee there are no definitions in the post ...<br>
>> >> >> > > > part.<br>
>> >> >> > > > All it<br>
>> >> >> > > > guarantees to eliminate are #:final and #:break.<br>
>> >> >> > > ><br>
>> >> >> > > > Carl Eastlund<br>
>> >> >> > > ><br>
>> >> >> > > ><br>
>> >> >> > > > On Fri, Sep 6, 2013 at 12:09 PM, Matthew Flatt<br>
>> >> >> > > > <<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>><br>
>> >> >> > > wrote:<br>
>> >> >> > > ><br>
>> >> >> > > > > The issue is `begin` splicing. The `result` form could be a<br>
>> >> >> > > > > `begin`<br>
>> >> >> > > > > form that contains definitions that are referenced by a<br>
>> >> >> > > > > preceding<br>
>> >> >> > > > > forms.<br>
>> >> >> > > > ><br>
>> >> >> > > > > For example, given<br>
>> >> >> > > > ><br>
>> >> >> > > > > (define (fish? v) (or (red? v) (blue? v)))<br>
>> >> >> > > > > (begin<br>
>> >> >> > > > > (define (red? v) ....)<br>
>> >> >> > > > > (define (blue? v) ....)<br>
>> >> >> > > > > 5)<br>
>> >> >> > > > ><br>
>> >> >> > > > > With `begin` splicing, that turns into<br>
>> >> >> > > > ><br>
>> >> >> > > > > (define (fish? v) (or (red? v) (blue? v)))<br>
>> >> >> > > > > (define (red? v) ....)<br>
>> >> >> > > > > (define (blue? v) ....)<br>
>> >> >> > > > > 5<br>
>> >> >> > > > ><br>
>> >> >> > > > > which is different than<br>
>> >> >> > > > ><br>
>> >> >> > > > > (define (fish? v) (or (red? v) (blue? v)))<br>
>> >> >> > > > > (let ()<br>
>> >> >> > > > > (define (red? v) ....)<br>
>> >> >> > > > > (define (blue? v) ....)<br>
>> >> >> > > > > 5)<br>
>> >> >> > > > ><br>
>> >> >> > > > > At Fri, 6 Sep 2013 11:15:50 -0400, Carl Eastlund wrote:<br>
>> >> >> > > > > > Is this function ever particularly necessary? Its<br>
>> >> >> > > > > > intended<br>
>> >> >> > > > > > use<br>
>> >> >> > > seems to<br>
>> >> >> > > > > be<br>
>> >> >> > > > > > like so:<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > (define-syntax (for/print stx)<br>
>> >> >> > > > > > (syntax-parse stx<br>
>> >> >> > > > > > [(_ clauses . body)<br>
>> >> >> > > > > > (with-syntax ([([pre ...] [post ...]) (split-for-body<br>
>> >> >> > > > > > #'body)])<br>
>> >> >> > > > > > (syntax<br>
>> >> >> > > > > > (for clauses<br>
>> >> >> > > > > > pre ...<br>
>> >> >> > > > > > (printf "~v/n" (let () post ...)))))]))<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > That way any #:break or #:final from the body ends up in<br>
>> >> >> > > > > > pre<br>
>> >> >> > > > > > ...,<br>
>> >> >> > > where<br>
>> >> >> > > > > the<br>
>> >> >> > > > > > enclosing for loop will interpret them, and post ... will<br>
>> >> >> > > > > > only<br>
>> >> >> > > include<br>
>> >> >> > > > > > normal definitions and expressions.<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > But it seems to me there's a much easier way that should<br>
>> >> >> > > > > > always<br>
>> >> >> > > > > > work:<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > (define-syntax-rule (for/print clauses pre ... result)<br>
>> >> >> > > > > > (for clauses<br>
>> >> >> > > > > > pre ...<br>
>> >> >> > > > > > (printf "~v\n" result)))<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > This not only puts all #:break and #:final clauses in pre<br>
>> >> >> > > > > > ...,<br>
>> >> >> > > > > > it<br>
>> >> >> > > should<br>
>> >> >> > > > > > guarantee result is an expression. Perhaps one should<br>
>> >> >> > > > > > still<br>
>> >> >> > > > > > write<br>
>> >> >> > > (let<br>
>> >> >> > > > > ()<br>
>> >> >> > > > > > result) in case result is (begin defn expr), but that's<br>
>> >> >> > > > > > still<br>
>> >> >> > > > > > simpler<br>
>> >> >> > > > > than<br>
>> >> >> > > > > > using split-for-body.<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > My question is -- have I overlooked some clever subtlety<br>
>> >> >> > > > > > here<br>
>> >> >> > > > > > that<br>
>> >> >> > > makes<br>
>> >> >> > > > > > split-for-body necessary, or is it usually easier to just<br>
>> >> >> > > > > > decompose<br>
>> >> >> > > pre<br>
>> >> >> > > > > ...<br>
>> >> >> > > > > > result rather than bothering with split-for-body?<br>
>> >> >> > > > > ><br>
>> >> >> > > > > > Carl Eastlund<br>
>> >> >> > > > > > _________________________<br>
>> >> >> > > > > > Racket Developers list:<br>
>> >> >> > > > > > <a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br>
>> >> >> > > > ><br>
>> >> >> > > > ><br>
>> >> >> > ><br>
>> >> >> > ><br>
>> >> >><br>
>> >> ><br>
>> >> ><br>
>> >> > _________________________<br>
>> >> > Racket Developers list:<br>
>> >> > <a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br>
>> >> ><br>
>> >><br>
>> ><br>
>><br>
><br>
<br>
</div></div></blockquote></div><br></div></div>