Racket 球拍:在一定范围内的懒惰评估

Racket 球拍:在一定范围内的懒惰评估,racket,lazy-evaluation,Racket,Lazy Evaluation,Racket提供了一个for lazy评估,它只需要在某个文件的开头添加一个#lang lazy头,就可以在整个文件中更改评估策略 然而,这种标准方法只允许课程级别的粒度;需要更精细的方法将惰性评估限制在某个定义的范围内 Racket是否提供了一些标准方法来将懒惰的评估策略限制在某个范围内?我正在寻找以下内容: (eval-lazy (+ 2 2)) ;; only available by explicit or implicit call-by-need #lang lazy是一种与#la

Racket提供了一个for lazy评估,它只需要在某个文件的开头添加一个
#lang lazy
头,就可以在整个文件中更改评估策略

然而,这种标准方法只允许课程级别的粒度;需要更精细的方法将惰性评估限制在某个定义的范围内

Racket是否提供了一些标准方法来将懒惰的评估策略限制在某个范围内?我正在寻找以下内容:

(eval-lazy (+ 2 2)) ;; only available by explicit or implicit call-by-need
#lang lazy
是一种与
#lang racket
完全不同的语言。是的,您可以混合和匹配某些部分,但在
#lang lazy
模块中处理来自
#lang lazy
的惰性值可能会变得混乱

每个方案,因此也包括诈骗,都有
延迟
强制

(define promise (delay (+ 2 2)))
(force promise) ; ==> 4
但是,这只是语法糖,因为您可以这样做:

(define promise (thunk (+ 2 2)))
(promise) ; ==> 4
当然,
thunk
只是匿名函数的语法糖,没有参数:

(define promise (lambda () (+ 2 2)))
(promise) ; ==> 4
现在
delay
实际上稍微复杂一些,因为如果调用这些函数,每次都会运行表达式。为了防止这种情况,我们将结果记录下来。在这里,我将把您的
eval lazy
实现为一个宏:

(define ^not-calculated (list #f)) ; unique value
(define-syntax eval-lazy
  (syntax-rules ()
    ((_ expression)
     (let ((value ^not-calculated))
       (lambda ()
         (when (eq? ^not-calculated value)
           (set! value expression))
         value)))))
thunk
lambda
一样,只要调用结果就会强制执行

Racket提供了一个可用于完成90%的算法的方法,您可以将每个步骤抽象为自己的过程,在这个过程中,您可以将它们组合在一起,而不会受到列表的惩罚。流只是
cons
中的延迟值,在
中普及,lang lazy
是一种与
\lang racket
完全不同的语言。是的,您可以混合和匹配某些部分,但在
#lang lazy
模块中处理来自
#lang lazy
的惰性值可能会变得混乱

每个方案,因此也包括诈骗,都有
延迟
强制

(define promise (delay (+ 2 2)))
(force promise) ; ==> 4
但是,这只是语法糖,因为您可以这样做:

(define promise (thunk (+ 2 2)))
(promise) ; ==> 4
当然,
thunk
只是匿名函数的语法糖,没有参数:

(define promise (lambda () (+ 2 2)))
(promise) ; ==> 4
现在
delay
实际上稍微复杂一些,因为如果调用这些函数,每次都会运行表达式。为了防止这种情况,我们将结果记录下来。在这里,我将把您的
eval lazy
实现为一个宏:

(define ^not-calculated (list #f)) ; unique value
(define-syntax eval-lazy
  (syntax-rules ()
    ((_ expression)
     (let ((value ^not-calculated))
       (lambda ()
         (when (eq? ^not-calculated value)
           (set! value expression))
         value)))))
thunk
lambda
一样,只要调用结果就会强制执行


Racket提供了一个可用于完成90%的算法的方法,您可以将每个步骤抽象为自己的过程,在这个过程中,您可以将它们组合在一起,而不会受到列表的惩罚。流只是
cons
中的延迟值,在中普及了一些评论:(1)
#lang lazy
与普通球拍非常相似,并且易于与普通球拍合作(例如,使用球拍承诺);(2) 因此,处理懒惰的价值观不会太混乱;(3) 可以使用子模块以较小的粒度工作;(4) 不,正确地实现承诺肯定不是“稍微复杂一点”,而是要复杂得多——我建议看一下racket实现,但更好的是:您的示例代码展示了一些微妙之处,因为它创建的闭包永远不会消失,因此总是会泄漏内存。@EliBarzilay 1-3:所以使用惰性库可以保证您可能需要强制执行。这比我想象的要容易一点。4:这可能就是为什么
delay
首先是一个方案原语。SICP可能在他们的视频中有同样的漏洞。我喜欢阅读球拍代码,所以有空的时候我会看一看。看来延迟既是一个过程,也是一个宏,从它的扩展。好吧,(1-2)它也给你
以递归方式强制值;(4) 不,出于其他原因,它是一个原始版本,但它很容易以导致内存泄漏的方式错误实现。我不记得视频中有什么内容,但请查看4.2中的“忘记不需要的环境”,以查看一个微妙但容易看到的问题,并查看指针和代码。一些注释:(1)
#lang lazy
被制作成非常类似于普通球拍,并且使其易于与普通球拍合作(例如,使用球拍承诺);(2) 因此,处理懒惰的价值观不会太混乱;(3) 可以使用子模块以较小的粒度工作;(4) 不,正确地实现承诺肯定不是“稍微复杂一点”,而是要复杂得多——我建议看一下racket实现,但更好的是:您的示例代码展示了一些微妙之处,因为它创建的闭包永远不会消失,因此总是会泄漏内存。@EliBarzilay 1-3:所以使用惰性库可以保证您可能需要强制执行。这比我想象的要容易一点。4:这可能就是为什么
delay
首先是一个方案原语。SICP可能在他们的视频中有同样的漏洞。我喜欢阅读球拍代码,所以有空的时候我会看一看。看来延迟既是一个过程,也是一个宏,从它的扩展。好吧,(1-2)它也给你
以递归方式强制值;(4) 不,出于其他原因,它是一个原始版本,但很容易以导致内存泄漏的方式错误实现它,我不记得视频中有什么内容,但请查看4.2中的“忘记不需要的环境”,以查看一个微妙但容易看到的问题,并查看指针和代码。