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