Racket流会记住他们的元素吗?

时间:2014-10-21 02:52:35

标签: stream racket

在从无限流中计算大量数字时,Racket是否会使用memoization?因此,例如,如果我打印出(也就是计算和显示)无限整数流上的前400个数字: (1 2 3 ... 399 400) 在我要求在这个无限流上打印前500个数字之后。第二组计算会使用memoization吗?那么前400个数字不会再计算出来了吗?

或者这个功能是否需要由用户编码/从库中获取?

3 个答案:

答案 0 :(得分:10)

内置racket/stream库使用延迟评估和memoization从流中绘制元素:

(require racket/stream)

(define (print-and-return x)
  (displayln "drawing element...")
  x)

(define (in-range-stream n m)
  (if (= n m)
      empty-stream
      (stream-cons (print-and-return n) (in-range-stream (add1 n) m))))

(define s (in-range-stream 5 10))

(stream-first s)
(stream-first s)
(stream-first (stream-rest s))

stream-consstream-first请求之前,不会评估传递给stream-rest的表达式。一旦评估,它们就会被记忆。请注意,尽管在s上执行了四个流操作,但只显示两个“绘图元素...”消息。

答案 1 :(得分:5)

您可以使用memoize包。

GitHub来源:https://github.com/jbclements/memoize/tree/master

raco pkg install memoize

使用它就像用define替换define/memo一样简单。引用它的例子:

(define (fib n)                                     
  (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))  

> (time (fib 35))                                   
cpu time: 513 real time: 522 gc time: 0             
14930352                                            

> (define/memo (fib n)                              
    (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))

> (time (fib 35))                                   
cpu time: 0 real time: 0 gc time: 0                 
14930352      

此外,使用Racket哈希表自己实现memoization通常很容易。

答案 2 :(得分:1)

对于使用SRFI 41流的其他Scheme实现,这些流也完全记忆所有物化元素。

事实上,在我的Guile端口SRFI 41(自2.0.9以来一直在Guile中),流的默认打印机将打印出所有已实现的元素(并且没有任何内容):

scheme@(guile-user)> ,use (srfi srfi-41)
scheme@(guile-user)> (define str (stream-from 0))
scheme@(guile-user)> (stream-ref str 4)
$1 = 4
scheme@(guile-user)> str
$2 = #<stream ? ? ? ? 4 ...>

任何未打印为?...的元素都已被记忆,不会重新计算。 (如果您对如何实现这样的打印机感到好奇,请点击此处the Guile version。)