首页 > 解决方案 > 如何重复应用函数以获得无限序列?

问题描述

例如,

(require racket/generator)
(define f add1)
(define init 0)
(in-producer (generator () (let loop ([x init]) (yield x) (loop (f x)))))

有没有更好的方法来做到这一点?我不太喜欢生成器,因为它们具有隐藏状态。

标签: racket

解决方案


使用可能是最简单的:

(require racket/stream)

;; X [X -> X] -> [Streamof X]
(define (repeated-fn-stream init f)
  (stream-cons init (repeated-fn-stream (f init) f)))

(repeated-fn-stream 0 add1)

序列

或者,使用序列和make-do-sequence

(require racket/sequence)

;; X [X -> X] -> [Sequenceof X]
(define (repeated-fn-sequence init f)
  ;; A "Pos" is an X that's the result of applying f repeatedly to init
  (define (pos->element pos) pos)
  (define (next-pos pos) (f pos))
  (define init-pos init)
  (make-do-sequence
   (λ ()
     (values pos->element
             next-pos
             init-pos
             #false
             #false
             #false))))

(repeated-fn-sequence 0 add1)

如果您想使用序列,并且想使用define-sequence-syntax使for循环专门化它:

(这对于“纯”功能是完全没有必要的,但它可能具有不同的性能特征)

(require (for-syntax syntax/parse))

(define-sequence-syntax in-repeated-fn-sequence
  (λ () #'repeated-fn-sequence) ; when used as a normal expression
  (syntax-parser                ; when used *directly* as a for-loop clause
    [[(x) (_ init-expr f-expr)]
     #'[(x) (:do-in
             ([(init) init-expr] [(f) f-expr])
             #true
             ([x init])
             #true
             ()
             #true
             #true
             [(f x)])]]))

(for/list ([x (in-repeated-fn-sequence 0 add1)]
           [i (in-range 10)])
  x)

使用时define-sequence-syntax,你应该确保每件事都有一个“单点真理”。因此,您经常会看到这种模式:

(define-sequence-syntax in-___
  (λ () #'in-___/proc) ; when used as a normal expression
  (syntax-parser
    ....everything that defines the actual functionality....))

;; This is completely determined by the sequence-syntax above,
;; that way there is NO duplicated functionality and NO chance for
;; it to get "out of sync".
(define (in-___/proc parameter ...)
  (for/stream ([elem (in-___ parameter ...)])
    elem))

这意味着,一旦您决定要使用define-sequence-syntax,您应该根据它来定义repeated-fn-sequence 函数

(define (repeated-fn-sequence init f)
  (for/stream ([elem (in-repeated-fn-sequence init f)])
    elem))

这样,如果in-repeated-fn-sequence需要更改以修复错误或切换表示,功能版本会自动更改。


推荐阅读