【问题标题】:Building accumulator for lazy lists in Racket在 Racket 中为惰性列表构建累加器
【发布时间】:2014-04-23 14:45:12
【问题描述】:

我定义了一个从零开始的所有整数的简单惰性列表:

(define integers-from
  (lambda (n) 
    (cons n
          (lambda () (integers-from (+ 1 n))))))

(define lz (integers-from 0))

我还编写了一个累加器,它获取一个惰性列表作为参数

(define lz-lst-accumulate
  (lambda (op initial lz)
    (if (null? lz)
        initial
        (cons (op (head lz) initial)  
              (lambda () (lz-lst-accumulate op (op initial (head lz)) (tail lz))))))) 

这个累加器能回答惰性列表的格式吗? 下面是对累加器的简单测试:

(define acc (lz-lst-accumulate * 1 lz))
(take acc 4)
=> '(1 2 6 24)

take 是一个辅助函数,它从惰性列表的第一个 n 元素创建一个列表:

(define head car)

(define tail
  (lambda (lz-lst)
     ((cdr lz-lst)) ))

(define take
  (lambda (lz-lst n)
    (if (= n 0)
        (list)
        (cons (car lz-lst)
              (take (tail lz-lst) (sub1 n)))) ))

【问题讨论】:

  • 请添加您对headtailtake 的定义。
  • @uselpa 我添加了定义

标签: scheme racket lazy-evaluation


【解决方案1】:

在您的lz-lst-accumulate 中,您计算​​一次(op (head lz) initial),然后还计算(op initial (head lz))。这是不一致的;两者都应该相同,并且实际上只计算一次,因为它是相同的值:

(define lz-lst-accumulate
  (lambda (op initial lz)
    (if (lz-lst-empty? lz)
        initial
        (let ((val (op (head lz) initial)))
           (cons val
              (lambda () (lz-lst-accumulate op val (tail lz))))))))

它在您的示例中仅适用于数字,因为您使用类型对称操作*。使用 cons 将无法正常工作。

除此之外没关系。 lz-lst-accumulate 通常称为 left fold(实际上,在 Haskell 中为 scanl,因为您会产生“累积”值的进展,foldl f z xs = last (scanl f z xs))。


re:您的take 版本,它强制流的元素太多。更好地实现它

(define take
  (lambda (lz n)
    (if (or (<= n 0) (lz-lst-empty? lz))
      (list)
      (if (= n 1)
        (list (car lz))      ; already forced
        (cons (car lz)
              (take (tail lz) (sub1 n)))))))

所以它只强制产生尽可能多的元素,而不是一个更多的元素(这可能是例如发散的,如(/ 1 0),无缘无故地使整个计算无效)。

这样,SRFI 41 中的反例((take 4 (stream-map 1/ (ints-from-by 4 -1)))就行了 (它计算 (1/4 1/3 1/2 1/1) 而不强制 1/0,这是 take 的常用版本,就像你正在使用的那样)。

【讨论】:

  • 你能说我不会使用缺点吗?因为我试过了,它按预期工作......非常感谢你的回答!
  • 这是我的荣幸,不客气。 :) 我的意思是 (cons a b)(cons b a) 不能产生相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 2020-10-10
  • 2016-07-05
  • 1970-01-01
相关资源
最近更新 更多