2

假设我有以下功能:

(define (g x) (f x))
(define (f x) (+ 1 x))

我想暂时g不同 f的电话。例如,像这样:

(let ((f (lambda (x) (+ 2 x))))
  (g 5))

我希望上面的代码评估为 7,但事实并非如此。相反,它的计算结果为 6,因为g调用了.f let

有没有一种方法可以做到这一点,而无需g在 内部重新定义,并且无需内联in 中let定义的整个主体?(在实践中,可能是一个非常庞大、复杂的函数)。gletg

4

4 回答 4

2

你要求的是动态而不是'f'的词法绑定。R6RS 和 R7RS 通过参数支持这一点。这将做你想要的:

(define f (make-parameter (lambda (x) (+ 1 x))))
(define (g x) ((f) x))

(display (g 5))(newline)

(parameterize ((f (lambda (x) (+ 2 x))))
  (display (g 5))(newline))
于 2018-02-22T23:48:57.913 回答
0

我找到了一种方法来做我想做的事,尽管我感觉很多人不会考虑这个犹太洁食:

(define (g x) (f x))

(define (f x) (+ 1 x))

(let ((old-f f))
  (set! f (lambda (x) (+ 2 x)))
  (let ((ans (g 5)))
    (set! f old-f)
    ans))
; -> 7

(g 5) ; -> 6

编辑回应下面的评论,我什至不知道这fluid-let是一件事。它甚至已经在 MIT-Scheme 上运行。这实际上正是我所需要的。如果下面的评论者发布这样的答案作为答案,它将成为接受的答案:

(define (g x) (f x))

(define (f x) (+ 1 x))

(fluid-let ((f (lambda (x) (+ x 2))))
  (g 5)) ; -> 7

(g 5) ; -> 6
于 2018-03-12T06:02:58.403 回答
0

您可以使用可选参数g来传递ffromlet表达式。

(define (g x . args)
  (if (null? args)
    (f x)
    ((car args) x)))

(let ((f (lambda (x) (+ 2 x))))
  (g 5 f))
于 2018-02-22T08:22:20.327 回答
0

我不确定你是否可以,但我绝不是方案专家。

我意识到您正在尝试在不重新定义g内部的情况下实现这一目标let,但是如何:

(define (h f x) (f x))
(define (g x) (h f x))
(define (f x) (+ 1 x))

(let ((f (lambda (x) (+ 2 x))))
  (h f 5))

这样,您就可以保留g当前调用位置的行为。但是如果你想暂时有不同的行为,你可以打电话h

更多代码用于澄清:

(let ((f (lambda (x) (+ 2 x))))
  (display (g 5)) ; 6
  (newline)
  (h f 5))        ; 7
于 2018-02-22T04:08:22.957 回答