Coding style 为什么let优先在方案中定义?

Coding style 为什么let优先在方案中定义?,coding-style,scheme,let,Coding Style,Scheme,Let,我总是这样写我的计划程序(并且看到它们被编写): (define (foo x) (let ((a ...)) ((b ...)) ...)) 我的一个学生写道: (define (foo x) (define a ...) (define b ...) ...) 两者的结果相同。我理解行为上的差异:第一个创建一个指向过程应用程序框架的新框架,而后者直接修改过程应用程序框架。后者将产生稍好的性能 另一个区别是前者避免在过程体中的指令序列之前使用隐式的be

我总是这样写我的计划程序(并且看到它们被编写):

(define (foo x)
  (let ((a ...))
       ((b ...))
    ...))
我的一个学生写道:

(define (foo x)
  (define a ...)
  (define b ...)
  ...)
两者的结果相同。我理解行为上的差异:第一个创建一个指向过程应用程序框架的新框架,而后者直接修改过程应用程序框架。后者将产生稍好的性能

另一个区别是前者避免在过程体中的指令序列之前使用隐式的
begin


为什么前一种是标准样式?

实际上,两种样式都可以

后者也不一定“直接修改程序应用框架”;内部定义与
letrec
(适用于R5RS兼容系统)或
letrec*
(适用于R6RS-和R7RS兼容系统)处理相同。因此,您的第二个示例实际上与以下示例相同:

(define (foo x)
  (letrec* ((a ...)
            (b ...))
    ...))

事实上,举一个例子,Racket将内部定义重写为其等价的
letrec*
表达式,因此性能上没有差异(当然,除了
let
letrec*
之间的差异之外)。

这不是完全等价的<过程体中的code>define更像是
letrec
,因此您可能会惊讶地发现,在
define
中的值绑定尚未完成且过程体尚未执行之前,您无法使用该值。假设你想做x+y*z:

(define (test x y z)
  (let ((ytimesz (* y z)))
     (let ((sum (+ x ytimesz)))
       (dosomething sum))))
这里之所以有嵌套let,是因为无法在创建时在同一let中访问
ytimesz
。我们有另一种特殊的形式,那就是
let*

(define (test x y z)
  (let* ((ytimesz (* y z)) (sum (+ x ytimesz)))
       (dosomething sum)))
letrec
letrec*
类似,但允许递归,因此在lambda中可以调用另一个绑定成员或其本身。现在,根据您使用的Scheme版本,您将在编写时获得以下选项之一:

(define (test x y z)
  (define ytimesz (* y z))
  (define answer (+ x ytimesz)) ;might work, might not
  (dosomething answer))
#中!R7RS
#!R6RS
#!球拍
完全可以,因为它被定义为
letrec*

#中!然而,R5RS根本不起作用。重写按
letrec
进行,它将所有变量(
ytimesz
answer
)初始化为未定义的值,然后将表达式的计算分配给
设置之前的临时变量-将变量转换为临时值的值,以确保所有使用的任何变量最终都是未定义的值,有些甚至是信号错误(Racket在R5RS模式下运行。对于在调用时计算主体中绑定的lambda表达式,这没有问题,它适用于这些
letrec
,而internal
define
最初用于


我使用
define
来存储简单的值和过程。第二,我想我需要使用一个预先计算的值,我可能会将整个过程重写为
let*
或者将
define
和一个简单的
let

组合起来。谢谢你纠正了我的误解。我们确实在使用Racket。也谢谢你在风格上的链接NK很多。你知道为什么过程中的定义与顶级定义的行为不同吗?R6RS内部定义,如R7RS内部定义,使用
letrec*
,而不是
letrec
@espertus,因为Scheme语言定义了两种不同的含义来定义
,一种用于顶级绑定,另一种基本上用于语法糖
letrec*
。这是适合您的方案。:-@ChrisJester Young固定R6RS。顶层差异一定是因为顶层实际上不是一个框架或仅仅是一个框架。顶层定义会改变“顶层框架”,但会在以后进行计算,然后再上一个
define
使其变得特别?