方案中嵌套定义的体面方式 [英] decent way of nested definition in scheme
问题描述
我想使用辅助功能(例如bar
)定义常量foo
.而且我想将bar
隐藏在foo
的定义内,所以我附带了以下代码:
I want to define a constant foo
using an auxiliary function, say, bar
. And I want to hide bar
inside the definition of foo
, so I come with this code:
(define foo
(define (bar n)
(+ n n))
(bar 1))
但是,此定义在许多方案实现中(语法方案,球拍,guile等)会导致语法错误.
However, this definition causes syntax errors in many scheme implementations(mit-scheme, racket, guile, etc.).
我有三种解决方法,但似乎都不令人满意:
I have three workarounds but none of them seems satisfactory:
(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创建一个编写辅助定义的环境,括号似乎在某种程度上令人困惑.
foo1
uses lambda to create an environment of writing auxiliary definitions and the parentheses seem somehow confusing.
foo2
使用let表达式,但我不能再使用语法糖(define (f n) ...)
=> (define f (lambda (n) ...))
foo2
uses let expression but I can no longer use the syntactic sugar (define (f n) ...)
=> (define f (lambda (n) ...))
foo3
与原始版本相比需要较少的修改,但是每次我想要此值时,都必须调用(foo3)
并重新进行计算.
foo3
requires less modification comparing with the original one, but every time I want this value, I have to call (foo3)
and do the computation all over again.
我的问题是:
- 我认为这种嵌套定义是有道理的,但是为什么将其视为语法错误?
- 是否有任何体面的方式来编写
foo
的定义?
- I think this kind of nested definition makes sense, but why it is considered a syntax error?
- is there any decent way to write the definition of
foo
?
推荐答案
回答您的问题:
-
define
仅可按规范.规范未涵盖您要执行的操作,因此会出现错误.如您所知,define
为表达式的值分配一个名称,只是您不能在其上下文中直接创建内部定义. - 但是还有其他一些表达式可以在这种情况下创建新的绑定.恕我直言
foo2
是这里最好的选择,它也是惯用的.如果bar
是递归定义,则可以使用letrec
.
define
can only be used in certain ways, as mandated by the specification. What you want to do isn't covered by the specification, hence the error. As you know,define
assigns a name to the value of an expression, it's just that you can't directly create internal definitions in its context.- But there are other expressions that allow creating new bindings in this context. IMHO
foo2
is the best option here, and it's idiomatic, too. And ifbar
were a recursive definition, you could useletrec
.
但是,如果失去一些语法糖会打扰您(由于在let
表达式中定义了过程的方式),请尝试使用
But if loosing a bit of syntactic sugar bothers you (because of the way procedures are defined inside a let
expression), then try using local
, it'll work in Racket:
(define foo
(local [(define (bar n) (+ n n))]
(bar 1)))
这篇关于方案中嵌套定义的体面方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!