Scheme 何时使用define和何时使用let-in球拍

Scheme 何时使用define和何时使用let-in球拍,scheme,racket,Scheme,Racket,我正在学习球拍,我有一个问题,关于什么时候使用define,什么时候使用let 我有这个功能: (define my-function (lambda (param1 param2 list1) (/ (count (lambda (x) (define a (param1 (remove x list1))) (define b (drop-right x 1)) (define c (param2 a x

我正在学习球拍,我有一个问题,关于什么时候使用
define
,什么时候使用
let

我有这个功能:

(define my-function
  (lambda (param1 param2 list1)
    (/
     (count
      (lambda (x)

        (define a (param1 (remove x list1)))

        (define b (drop-right x 1))

        (define c (param2 a x-sin-clase))

        (eq? (last x) (last c)))
      (cdr list1))
     (length (cdr list1))))) 
不知道上述函数的作用。在函数体内部使用
定义
是否正确


我在某个地方读到,
define
用于声明全局变量,
let
用于声明局部变量。我查看了racket的文档,但没有提到任何区别。

一个区别:内部定义在一个相互递归的范围内,但let绑定不是

这意味着比在<代码>中让<代码>:

(let ([x expr-1] [y expr-2])
  body)
expr-1
expr-2
不能引用
x
y
。更具体地说,

(let ([x (stream-cons 1 y)] [y (stream-cons 2 x)])
  x)
;error=> y: unbound identifier in: y
(require racket/block)

(block
  (define x (stream-cons 1 y))
  (define y (stream-cons 2 x))
  (stream->list (stream-take x 5)))
;=> (list 1 2 1 2 1)
如果
x
y
是在
let
之外定义的,则expr-1和expr-2将引用外部定义,而不是let引入的定义。具体地说:

(define x 'outer)
(let ([x 'inner] [y x]) ; <- this x refers to outer,
  y)                    ;    so y is 'outer
;=> 'outer
expr-1
expr-2
可参考
x
y
。具体地说,

(let ([x (stream-cons 1 y)] [y (stream-cons 2 x)])
  x)
;error=> y: unbound identifier in: y
(require racket/block)

(block
  (define x (stream-cons 1 y))
  (define y (stream-cons 2 x))
  (stream->list (stream-take x 5)))
;=> (list 1 2 1 2 1)
定义的范围
x
f
的主体中随处可见,但不在其外部。这意味着它在
B
C
D
E
中可见,但在A或F中不可见

a
let
在这里,
x
let
的主体中随处可见,但不在其外部。这意味着它在
E
中可见,但在A、B、C、D或F中不可见

let*
在这里,
x
let*
的主体中以及之后的
let*
绑定中随处可见,但不在其外部。这意味着它在
D
E
中可见,但在A、B、C或F中不可见

letrec的范围
x
letrec
的主体和
letrec
的绑定中随处可见,但不在其外部。这意味着它在
B
C
D
E
中可见,但在A或F中不可见


letrec
中变量的范围和本地
define
变量的范围非常相似,因为
letrec
define
都使用相互递归的范围。

我终于明白了我读到的
define
的变量是“全局变量”

在《Scheme编程语言第四版》一书中,R.Kent Dybvig一节说:

由let和lambda表达式绑定的变量不可见 在这些表达的主体之外


一个区别是:内部
define
s在一个相互递归的范围内(包括mut rec函数),
let
绑定不是,但也有其他样式reasons@AlexKnauth对不起,关于你的评论我什么都不懂。谢谢。在
(let([x expr-1][y expr-2])body)
中,expr-1和expr-2不能引用
x
y
。但是,在
(block(define x expr-1)(define y expr-2)body)
中,expr-1和expr-2都可以引用
x
y
。从技术上讲
define
仅在顶层“允许”。在本地定义上下文中使用时,它们只是语法糖,将被扩展为适当的
let
形式。那么,在体函数中使用let是否更好?谢谢。当我需要“更改”函数输入,使其成为更好的“更一致”形式时,我发现
let
最有用。例如,如果一个函数使用
符号
[Listof Symbol]
,但我想将函数体编写为一致的
[Listof Symbol]
,我可以使用
let
来隐藏参数并使其成为一个列表<代码>(定义(fx)(let([x(if(list?x)x(list x))))…body…)
我有点被这些不同的作用域所淹没。是否有关于其使用量百分比的统计数据?到目前为止,我们主要使用define和一些let,这似乎已经足够了。我们需要这么多选项吗?我不知道任何具体的统计数据,但在我读过或研究过的代码中,内部定义比let更常见。我通常只在特殊情况下使用let,比如定义不允许或我故意使用“规范化”版本进行跟踪,对于其他所有情况,我使用定义使用“规范化”版本?如果定义在局部范围内,则定义的变量不是全局变量。
(define(f)(define x 5)…body…)
中的
x
仅在
f
的主体内部可见,而不是外部可见。@AlexKnauth可能我还没有理解我的教授。他说:“Define应该只用于定义全局变量。要从函数中定义局部变量,必须使用let或let*。否则,全局变量可能会干扰函数的局部功能。”你的教授说的到底是哪种语言?这听起来像是一个奇怪的语言功能,我想尝试一下。我只是尝试在Racket中使用一个内部定义,而
x
在外部看不到,它不是“全局的”。那么你的教授是什么意思呢?@AlexKnauth他说这是关于结束的,
....A....
(define (f)
  (let ([t1 ..B..]
        [x ..C..]
        [t2 ..D..])
    ....E....))
....F....
....A....
(define (f)
  (let* ([t1 ..B..]
         [x ..C..]
         [t2 ..D..])
    ....E....))
....F....
....A....
(define (f)
  (letrec ([t1 ..B..]
           [x ..C..]
           [t2 ..D..])
    ....E....))
....F....