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))
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
uses lambda to create an environment of writing auxiliary definitions and the parentheses seem somehow confusing.
foo2
uses let expression but I can no longer use the syntactic sugar (define (f n) ...)
=> (define f (lambda (n) ...))
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.
My questions are:
- 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
?
Answering your questions:
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.foo2
is the best option here, and it's idiomatic, too. And ifbar
were a recursive definition, you could useletrec
.But if loosing a bit of syntactic sugar bothers you (because of the way procedures are defined inside a
let
expression), then try usinglocal
, it'll work in Racket: