【问题标题】:Do Racket streams memoize their elements?Racket 流会记住它们的元素吗?
【发布时间】:2014-12-16 04:11:00
【问题描述】:

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

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

【问题讨论】:

    标签: stream racket


    【解决方案1】:

    内置的racket/stream 库使用惰性求值和记忆来从流中绘制元素:

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

    【讨论】:

    • 哦!我从未尝试过racket/stream。您的回答更具体到原始问题。投票赞成。
    【解决方案2】:

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

    事实上,在我的 SRFI 41 的 Guile 端口中(自 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。)

    【讨论】:

      【解决方案3】:

      您可以使用memoize 包。

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

      raco pkg install memoize

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

      (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 哈希表自己实现记忆化通常很容易。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-18
        • 1970-01-01
        • 2015-12-29
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 2014-11-10
        • 1970-01-01
        相关资源
        最近更新 更多