我今天正在玩Racket,并尝试根据同一功能的多个应用程序生成一个不确定的数字序列。
在Clojure中我会使用 iterate 函数,但我不确定Racket中的等价物是什么。
答案 0 :(得分:6)
SRFI 41((require srfi/41)
)直接提供stream-iterate
。
您可以使用Óscar的示例,并在stream-iterate
的任何地方替换iterate
,而无需定义自己的iterate
。此外,您可以使用match-lambda
:
(require srfi/41)
(define fib
(stream-map first
(stream-iterate (match-lambda
((list a b)
(list b (+ a b))))
'(0 1))))
(stream->list 10 fib) ; => (0 1 1 2 3 5 8 13 21 34)
答案 1 :(得分:5)
内置的Racket程序中没有直接的等价物,但我们可以使用streams实现具有类似功能的东西。试试这个:
(define (stream-take m s)
(if (zero? m)
'()
(cons (stream-first s)
(stream-take (sub1 m) (stream-rest s)))))
(define (iterate f x)
(stream-cons x (iterate f (f x))))
例如,以下是Clojure documentation中的示例在Racket中的样子:
(stream-take 5 (iterate add1 5))
=> '(5 6 7 8 9)
(stream-take 10 (iterate (curry + 2) 0))
=> '(0 2 4 6 8 10 12 14 16 18)
(define powers-of-two (iterate (curry * 2) 1))
(stream-ref powers-of-two 10)
=> 1024
(stream-take 10 powers-of-two)
=> '(1 2 4 8 16 32 64 128 256 512)
(define fib
(stream-map first
(iterate (lambda (pair)
(list (second pair)
(+ (first pair) (second pair))))
'(0 1))))
(stream-take 10 fib)
=> '(0 1 1 2 3 5 8 13 21 34)
答案 2 :(得分:5)
在大多数情况下,您可以将iterate
替换为for/fold
。
> (define (mult2 x) (* x 2))
> (for/fold ([x 1]) ; the initial value of x is 1
([i 8]) ; count i=0,...,7
(mult2 x)) ; put x = (mult2 x)
256
for/fold
的优势在于您可以一次迭代更多变量:
(define (mult2 x) (* x 2))
(define (div2 x) (/ x 2))
(for/fold ([x 1] ; bind x to 1
[y 1]) ; bind y to 1
([i 8]) ; i=0,...,7
(values (mult2 x) ; put x = (mult2 x)
(div2 y))) ; put y = (div2 y)
这将返回两个值:256
和1/256
。
收集元素很容易。这是斐波那契的例子:
(for/fold ([fs '(1)] ; list of fibonacci numbers generated so far
[f1 1] ; a fibonacci number
[f2 1]) ; the following fibonacci number
([i 10]) ; i = 0,...,9
(values (cons f2 fs) ; cons the new fibonacci number to the list fs
f2 ; put f1 = (the old) f2
(+ f1 f2))) ; put f2 = (the old) f1+f2
结果包含三个值:
'(89 55 34 21 13 8 5 3 2 1 1)
89
144
答案 3 :(得分:4)
基于soegaard使用渴望理解的想法,这里有一个in-nest-sequence
序列生成器(也可用on Code Review和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 ...))])])))
由in-nest-sequence
生成的序列不会终止,因此您需要将其与执行的序列或#:break
或类似的终止条件配对。例如(使用Óscar答案中的powers-of-two
示例):
;; 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
这是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