> I thought I'd also tried `in-producer' without > success, but I may have made a mistake.
I had difficulty with the `stop' arg to `in-producer'. It can't simply be void or void?. I looped back to try this again, and finally figured it out (although maybe the following isn't the most concise way to put it?): (define (in-gen-multi) (define (stop? . xs) (match xs [(list 'end 'end) #t] [else #f])) (in-producer (generator () (for ([i (in-range 4)]) (yield i 0)) (yield 'end 'end)) stop?)) (for/list ([(x y) (in-gen)]) (cons x y)) OK, so now I'm even interested in my question about generator performance. Because it would be elegant to express what I want using a generator. On Fri, Sep 14, 2012 at 9:14 AM, Greg Hendershott <greghendersh...@gmail.com> wrote: > Thank you Matthew. I thought I'd also tried `in-producer' without > success, but I may have made a mistake. > > Since I posted, I realized I don't need to use a generator at all, so > I'm not road-blocked. > > Speaking of which, I'm curious what are folks' attitudes toward > generators? I ask because I rarely see them used in Racket code I've > perused. Is that just because generators are relatively new? Or is it > because they are convenient but somewhat "heavy" performance-wise? > > On Fri, Sep 14, 2012 at 8:53 AM, Matthew Flatt <mfl...@cs.utah.edu> wrote: >> At Fri, 14 Sep 2012 08:20:22 -0400, Greg Hendershott wrote: >>> tl'dr: I can `yield' multiple values when an `in-generator' sequence >>> is used directly in a comprehension, but not when it is returned from >>> a function. I'm stumped. >>> >>> >>> Let's try using the `in-generator' sequence directly in a comprehension: >>> >>> ;; Yield 1 value, directly using `in-generator` >>> (for/list ([x (in-generator (for ([i (in-range 4)]) >>> (yield i)))]) >>> x) >>> ;; => '(0 1 2 3) >>> >>> ;; Yield 2 values, directly using `in-generator` >>> (for/list ([(x y) (in-generator (for ([i (in-range 4)]) >>> (yield i 0)))]) >>> (cons x y)) >>> ;; => '((0 . 0) (1 . 0) (2 . 0) (3 . 0)) >>> >>> Great! >>> >>> Next, let's try using the `in-generator' sequence as returned from a >>> function. As best I can understand from the docs, this should work. It >>> does for the case of yield-ing 1 value -- but not 2 values: >>> >>> ;; Yield 1 value, using `in-generator' returned from a function: >>> (define (in-gen-1) >>> (in-generator (for ([i (in-range 4)]) >>> (yield i)))) >>> (for/list ([x (in-gen-1)]) >>> x) >>> ;; => '(0 1 2 3) >>> >>> ;; Yield 2 values, using `in-generator' returned from a function: >>> (define (in-gen-2) >>> (in-generator (for ([i (in-range 4)]) >>> (yield i 0)))) >>> (for/list ([(x y) (in-gen-2)]) >>> (cons x y)) >>> ;; ==> EXCEPTION: >>> ; .../private/for.rkt:1046:17: arity mismatch; >>> ; the expected number of arguments does not match the given number >>> ; expected: 1 >>> ; given: 2 >>> ; arguments...: >>> ; 0 >>> ; 0 >>> >>> Why? >> >> It's a problem in `in-generator' --- specifically in the way that >> `in-generator' expands to `in-producer' when the `in-generator' >> expression is not in a `for' right-hand side. In that case, the >> `in-generator' expansion doesn't know how many "stop" values it's >> supposed to produce. >> >> >> To work around the problem, you can use `in-producer' and `generator': >> >> ;; Yield 2 values, using `in-generator' returned from a function: >> (define (in-gen-2) >> (in-producer (generator () >> (for ([i (in-range 4)]) >> (yield i 0)) >> (values 'done 'done)) >> (lambda (a b) (eq? a 'done)))) >> >> (for/list ([(x y) (in-gen-2)]) >> (cons x y)) >> >> >> I'll work on a repair for `in-generator'. >> ____________________ Racket Users list: http://lists.racket-lang.org/users