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
?
foo1
andfoo2
are equivalent (let
useslambda
under the hood). On the other hand,foo3
is defining a new function, not a constant value as the other options, so it's not equivalent. – Óscar Lópezdefine
s (which are recursive) is withletrec
:(define foo (letrec ((bar (lambda(n) (+ n n)))) (bar 1)))
. which is equivalent to the (more popular) "namedlet
" construct,(define foo (let bar ((n 1)) (+ n n)))
(even thoughbar
isn't called recursively here at all). – Will Ness