Аккумулятор для бесконечных потоков - PullRequest
3 голосов
/ 08 марта 2019

Я пытаюсь реализовать аккумулятор для бесконечного потока.Я написал следующий код, но он работает в бесконечном цикле и не может завершить

(define (stream-first stream) (car stream))
(define (stream-second stream) (car ((cdr stream))))
(define (stream-third stream) (car ((cdr ((cdr stream))))))
(define (stream-next stream) ((cdr stream)))


(define (stream-foldl func accum stream)
    (cond
         [(empty? stream) accum]
         [else (stream-foldl func (func (stream-first stream) accum) (stream-next stream))] ))

Я написал несколько тестов, чтобы продемонстрировать, что я пытаюсь реализовать

(define (natural-nums)
   (define (natural-nums-iter n)
   (thunk
   (cons n (natural-nums-iter (+ n 1)))))
   ((natural-nums-iter 0)))

(define x (stream-foldl cons empty (natural-nums)))
(check-equal? (stream-first x) empty)
(check-equal? (stream-second x) (list 0))
(check-equal? (stream-third x) (list 1 0))

(define y (stream-foldl (curry + 1) 10 (naturals)))
(check-equal? (stream-first y)  10)
(check-equal?  (stream-second y) 11)
(check-equal?  (stream-third y)  13)

Вот след моей функции stream-foldl

>(stream-foldl
  #<procedure:cons>
  '()
  '(0 . #<procedure:...9/saccum.rkt:25:0>))
()>(stream-foldl
  #<procedure:cons>
  '(0)
  '(1 . #<procedure:...9/saccum.rkt:25:0>))
(0)>(stream-foldl
  #<procedure:cons>
  '(1 0)
  '(2 . #<procedure:...9/saccum.rkt:25:0>))
(1 0)>....

Мне кажется, что я не могу правильно установить базовый случай, поэтому никогда не завершаюсь из рекурсивного вызова

1 Ответ

3 голосов
/ 08 марта 2019

Fold должен просматривать каждый элемент в потоке, а затем производить результат на основе этих элементов. С бесконечным потоком неудивительно, что сгиб не заканчивается (как бы вы могли посмотреть на каждый элемент в бесконечном потоке?).

Что вы можете сделать:

Создание конечного потока из бесконечного потока. stream-take может быть использовано для этого. Пример реализации stream-take:

;; Returns a stream containing the first n elements of stream s.
(define (stream-take n s)
  (cond ((zero? n) empty-stream)
        ((empty? s) (error "Stream is shorter than n")
        (else
          (delay (stream-first s)
                 (stream-take (- n 1) (stream-rest s)))))))
          ; Note: 'delay' is the same as the 'thunk' in your code.

Затем сверните конечный поток либо используя вашу реализацию fold, либо stream-fold.

...