方案中嵌套定义的体面方式 [英] decent way of nested definition in scheme

查看:92
本文介绍了方案中嵌套定义的体面方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用辅助功能(例如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.

我的问题是:

  1. 我认为这种嵌套定义是有道理的,但是为什么将其视为语法错误?
  2. 是否有任何体面的方式来编写foo的定义?
  1. I think this kind of nested definition makes sense, but why it is considered a syntax error?
  2. is there any decent way to write the definition of foo?

推荐答案

回答您的问题:

  1. define仅可按规范.规范未涵盖您要执行的操作,因此会出现错误.如您所知,define为表达式的值分配一个名称,只是您不能在其上下文中直接创建内部定义.
  2. 但是还有其他一些表达式可以在这种情况下创建新的绑定.恕我直言foo2是这里最好的选择,它也是惯用的.如果bar是递归定义,则可以使用letrec.
  1. 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.
  2. 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 if bar were a recursive definition, you could use letrec.

但是,如果失去一些语法糖会打扰您(由于在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆