如何延迟/延迟计算 Racket 中函数的参数?



我待在球拍 #lang 内。 我正在尝试弄清楚如何延迟函数参数的计算 - 我无法更改传入的参数。 例如,假设我想传入,执行以下操作:

(define (a e) 6)

然后我想用这个参数调用一个

(a (/ 1 0))

我怎样才能延迟对这个论点的评估?

我尝试做类似的事情(在函数 a 中):

(define (a e) (define E (lambda () e)) 6)

但这仍然首先评估了论点。有什么建议吗?

#lang racket是一种渴望的语言,但由于它的早期是R5RS方案,它仍然具有R5RS兼容delayforce

(define (test delayed-e) 6)
(test (delay (/ 1 0)))
; ==> 6

如果没有特殊表格,您可以执行以下操作:

(test (thunk (/ 1 0)))
; ==> 6
;; the same as
(test (lambda () (/ 1 0)))
; ==> 6

请注意,在调用函数时都需要执行此操作,因为您需要在语言计算值之前包装它们。在像#lang lazy这样的懒惰语言中,你可以天真地编写代码,它会做正确的事情。

#lang lazy
(define (test e) 6)
(test (/ 1 0))
; ==> 6

现在#lang lazy的实现是使用delayforce装饰宏,因此核心可能是相同的,只是表面语言略有不同。 如果在一种热切的语言中存在同样易于使用的惰性求值,我们就不会使用惰性语言了。

编辑

宏是对实际代码进行计算的一种方法。因此,如果你把你的函数变成一个宏,你可以让它变成你想要的任何内容:

(define-syntax test 
(syntax-rules ()
((_ ignored-edpression) 6)))
(test (/ 1 0))
; ==> 6 

知道这会用6替换代码并不重要。您可以改为将其包装:

(define-syntax define-lazy
(syntax-rules ()
((_ (name args ...) body ...)
(begin
(define (impl args ...)
body ...)
(define-syntax name
(syntax-rules ()
((_ margs (... ...)) (impl (delay margs) (... ...)))))))))
(define-lazy (test e) 6)
(test (/ 1 0))
; ==> 6

如果你看一下它扩展的内容(test (/1 0))它看起来像第一个示例。与懒惰的语言不同,您需要明确地force正文中的参数。

(define-lazy (my-if p c a)
(if (force p)
(force c)
(force a)))
(my-if (< 3 4) 10 (/ 1 0))
; ==> 10

最新更新