Do Racket streams memoize their elements?

后端 未结 3 1795
眼角桃花
眼角桃花 2021-01-06 04:40

Does Racket use memoization when computing large amounts of numbers from an infinite stream? So, for example, if I printed out (aka, computed and displayed) the first 400 nu

相关标签:
3条回答
  • 2021-01-06 04:55

    You can use the memoize package.

    GitHub source: https://github.com/jbclements/memoize/tree/master

    raco pkg install memoize

    Using it is as simple as replacing define with define/memo. To quote its example:

    (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      
    

    Also, it is generally quite easy to implement memoization yourself using a Racket hash-table.

    0 讨论(0)
  • 2021-01-06 05:02

    For other Scheme implementations that use SRFI 41 streams, those streams also fully memoise all the materialised elements.

    In fact, in my Guile port of SRFI 41 (which has been in Guile since 2.0.9), the default printer for streams will print out all the elements so materialised (and nothing that isn't):

    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 ...>
    

    Any of the elements that aren't being printed out as ? or ... have already been memoised and won't be recomputed. (If you're curious about how to implement such a printer, here's the Guile version.)

    0 讨论(0)
  • 2021-01-06 05:03

    The built-in racket/stream library uses lazy evaluation and memoization to draw elements from a 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))
    

    The expressions passed to stream-cons are not evaluated until requested either with stream-first or stream-rest. Once evaluated, they are memoized. Notice that despite the four stream operations performed on s, only two `"drawing element..." messages are displayed.

    0 讨论(0)
提交回复
热议问题