【发布时间】:2014-01-03 04:18:03
【问题描述】:
我想使用一个辅助函数定义一个常量foo,比如bar。我想在foo的定义中隐藏bar,所以我来了这个代码:
(define foo
(define (bar n)
(+ n n))
(bar 1))
但是,此定义会在许多方案实现(mit-scheme、racket、guile 等)中导致语法错误。
我有三种解决方法,但似乎都不令人满意:
(define foo1
((lambda ()
(define (bar n)
(+ n n))
(bar 1))))
(define foo2
(let ((bar (lambda (n) (+ n n))))
(bar 1)))
(define (foo3)
(define (bar n)
(+ n n))
(bar 1))
foo1 使用 lambda 来创建编写辅助定义的环境,而括号似乎有些混乱。
foo2 使用 let 表达式,但我不能再使用语法糖 (define (f n) ...) => (define f (lambda (n) ...))
foo3 与原来的相比,需要的修改更少,但每次我想要这个值时,我都必须调用(foo3) 并重新进行计算。
我的问题是:
- 我觉得这种嵌套定义是有道理的,但是为什么会被认为是语法错误呢?
- 有没有像样的方法来写
foo的定义?
【问题讨论】:
-
foo1和foo2是等价的(let在后台使用lambda)。另一方面,foo3定义了一个新函数,而不是像其他选项那样的常量值,所以它不等价。 -
重写嵌套
defines(是递归的)的标准和正确方法是使用letrec:(define foo (letrec ((bar (lambda(n) (+ n n)))) (bar 1)))。这相当于(更流行的)“命名为let” 构造(define foo (let bar ((n 1)) (+ n n)))(尽管bar在这里根本没有被递归调用)。 -
(define foo1 ((lambda () (define (bar n) (+ n n)) (bar 1)))),这个有多余的括号,去掉lambda周围的一对括号;像这样 (define foo1 (lambda () (define (bar n) (+ n n)) (bar 1)))。它有效。
标签: scheme racket mit-scheme guile