我将留在#lang球拍内。 我试图弄清楚如何延迟函数参数被评估 - 我不能改变传入的参数。 例如,假设我想传递这样的事情:
(define (a e) 6)
然后我想用这个论点打电话给
(a (/ 1 0))
我如何推迟评估这个论点?
我尝试过(在函数a中):
(define (a e)
(define E (lambda () e))
6)
但是这仍然首先评估论证。有什么建议吗?
答案 0 :(得分:2)
#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