我待在球拍 #lang 内。 我正在尝试弄清楚如何延迟函数参数的计算 - 我无法更改传入的参数。 例如,假设我想传入,执行以下操作:
(define (a e) 6)
然后我想用这个参数调用一个
(a (/ 1 0))
我怎样才能延迟对这个论点的评估?
我尝试做类似的事情(在函数 a 中):
(define (a e)
(define E (lambda () e))
6)
但这仍然首先评估了论点。有什么建议吗?
#lang racket
是一种渴望的语言,但由于它的早期是R5RS方案,它仍然具有R5RS兼容delay
和force
:
(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
的实现是使用delay
和force
装饰宏,因此核心可能是相同的,只是表面语言略有不同。 如果在一种热切的语言中存在同样易于使用的惰性求值,我们就不会使用惰性语言了。
编辑
宏是对实际代码进行计算的一种方法。因此,如果你把你的函数变成一个宏,你可以让它变成你想要的任何内容:
(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