Sulla base dell'idea di Soegaard usare comprensioni ansiosi, ecco un generatore in-nest-sequence
sequenza (disponibile anche on Code Review e as a Gist):
#lang racket
(require (for-syntax unstable/syntax))
(provide (rename-out [*in-nest-sequence in-nest-sequence]))
(define in-nest-sequence
(case-lambda
[(func init)
(make-do-sequence
(thunk (values identity func init #f #f #f)))]
[(func . inits)
(make-do-sequence
(thunk (values (curry apply values)
(lambda (args)
(call-with-values (thunk (apply func args)) list))
inits #f #f #f)))]))
(define-sequence-syntax *in-nest-sequence
(lambda() #'in-nest-sequence)
(lambda (stx)
(syntax-case stx()
[[(x ...) (_ func init ...)]
(unless (= (syntax-length #'(x ...)) (syntax-length #'(init ...)))
(raise-syntax-error 'in-nest-sequence
(format "~a values required" (syntax-length #'(x ...)))
stx #'(init ...)))
(with-syntax ([for-arity (syntax-length #'(init ...))]
[(value ...) (generate-temporaries #'(init ...))]
[(y ...) (generate-temporaries #'(init ...))])
#'[(x ...) (:do-in ([(f) func])
(unless (procedure-arity-includes? f for-arity)
(raise-arity-error f (procedure-arity f) init ...))
([value init] ...)
#t
([(x ...) (values value ...)]
[(y ...) (f value ...)])
#t
#t
(y ...))])])))
Le sequenze generate da in-nest-sequence
non terminano, quindi sarà necessario accoppiarle con eithe r una sequenza o una condizione di terminazione simile o #:break
o simile. Per esempio (utilizzando l'esempio powers-of-two
in risposta di Óscar):
;; first ten powers of 2
(for/list ((_ (in-range 10))
(x (in-nest-sequence (curry * 2) 1)))
x)
; => (1 2 4 8 16 32 64 128 256 512)
;; powers of 2 above 10,000 and below 1,000,000
(for/list ((x (in-nest-sequence (curry * 2) 1))
#:when (> x 10000)
#:break (> x 1000000))
x)
; => (16384 32768 65536 131072 262144 524288)
;; first power of 2 above 10,000,000
(for/first ((x (in-nest-sequence (curry * 2) 1))
#:when (> x 10000000))
x)
; => 16777216
Ed ecco l'esempio sequenza di Fibonacci:
;; first ten Fibonacci numbers
(for/list ((_ (in-range 10))
((x y) (in-nest-sequence (lambda (a b) (values b (+ a b))) 0 1)))
x)
; => (0 1 1 2 3 5 8 13 21 34)
;; first Fibonacci number above 10,000,000
(for/first (((x y) (in-nest-sequence (lambda (a b) (values b (+ a b))) 0 1))
#:when (> x 10000000))
x)
; => 14930352
fonte
2015-10-04 17:36:59
Inoltre - si aspettano 'per/fold' di essere più veloce di flusso. – soegaard
Bene, ovviamente le comprensioni entusiaste sono molto più leggere dei flussi. ;-) In realtà dovrei scrivere un generatore di sequenza 'in-iterate' che può essere usato direttamente con' for' comprehensions. –
@ ChrisJester-Young Questa è una bella idea. – soegaard