如何延迟/延迟评估Racket中函数的参数?

时间:2017-11-21 15:32:06

标签: racket lazy-evaluation divide-by-zero

我将留在#lang球拍内。 我试图弄清楚如何延迟函数参数被评估 - 我不能改变传入的参数。 例如,假设我想传递这样的事情:

(define (a e) 6)

然后我想用这个论点打电话给

(a (/ 1 0))

我如何推迟评估这个论点?

我尝试过(在函数a中):

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

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

1 个答案:

答案 0 :(得分:2)

#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