scheme – When to use define and when to use let in racket
Table of Contents
scheme – When to use define and when to use let in racket
One difference: Internal defines are in a mutually recursive scope, but let bindings are not.
This means than in a let
:
(let ([x expr-1] [y expr-2])
body)
The expr-1
and expr-2
cannot refer to x
or y
. More concretely,
(let ([x (stream-cons 1 y)] [y (stream-cons 2 x)])
x)
;error=> y: unbound identifier in: y
And if x
or y
is defined outside of the let
, expr-1 and expr-2 will refer to the outer definitions, and not the ones introduced by the let. Concretely:
(define x outer)
(let ([x inner] [y x]) ; <- this x refers to outer,
y) ; so y is outer
;=> outer
However, internal defines have a mutually recursive scope, which means that in
(block
(define x expr-1)
(define y expr-2)
body)
The expr-1
and expr-2
can refer to x
or y
. Concretely,
(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)
The Scope of a define
....A....
(define (f)
(define t1 ..B..)
(define x ..C..)
(define t2 ..D..)
....E....)
....F....
The x
is visible everywhere in the body of f
, but not outside that. That means its visible in B
, C
, D
, and E
, but not in A or F.
The Scope of a let
....A....
(define (f)
(let ([t1 ..B..]
[x ..C..]
[t2 ..D..])
....E....))
....F....
Here the x
is visible everywhere in the body of the let
, but not outside that. That means its visible in E
, but not in A, B, C, D, or F.
The Scope of a let*
....A....
(define (f)
(let* ([t1 ..B..]
[x ..C..]
[t2 ..D..])
....E....))
....F....
Here the x
is visible everywhere in the body of the let*
and in let*
bindings that come after it, but not outside that. That means its visible in D
and E
, but not in A, B, C, or F.
The Scope of a letrec
....A....
(define (f)
(letrec ([t1 ..B..]
[x ..C..]
[t2 ..D..])
....E....))
....F....
The x
is visible everywhere in the body of the letrec
and in the bindings of the letrec
, but not outside that. That means its visible in B
, C
, D
, and E
, but not in A or F.
The scope of variables in letrec
and the scope of local define
variables are very similar because both letrec
and define
work with mutually recursive scopes.
Ive finally understood what I have read that define
s variable are global variables.
In the book The Scheme Programming Language Fourth Edition, R. Kent Dybvig, section 2.6. Top Level Definitions says:
The variables bound by let and lambda expressions are not visible
outside the bodies of these expressions.