假设我有以下功能:
(define (g x) (f x))
(define (f x) (+ 1 x))
我想暂时使用不同的 g
来呼叫f
。例如,像这样:
(let ((f (lambda (x) (+ 2 x))))
(g 5))
我会喜欢上面的代码来评估为7,但事实并非如此。相反,它评估为6,因为g
将f
调用{/ 1}}的范围。
如果没有在let
内重新定义g
,并且没有在let
中内联g
的全部内容,是否有办法做到这一点? (实际上,let
可能是一个非常庞大,复杂的功能。)
答案 0 :(得分:1)
你要求的是动态而不是词汇绑定' 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))
答案 1 :(得分: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
答案 2 :(得分:0)
您可以使用g
中的可选参数从f
表达式传递let
。
(define (g x . args)
(if (null? args)
(f x)
((car args) x)))
和
(let ((f (lambda (x) (+ 2 x))))
(g 5 f))
答案 3 :(得分: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