Reputation: 1940
In Common Lisp I can evaluate the following snippet of code (in SBCL) without being signalled any syntax error:
(let ((x 0))
(defun my-incf (y)
(setf x (+ x y)))
(defun my-decf (y)
(setf x (- x y))))
MY-DECF
CL-USER> (my-incf 1)
1
CL-USER> (my-incf 1)
2
CL-USER> (my-decf 1)
1
CL-USER> (my-decf 1)
0
When I try to evaluate a corresponding Scheme snippet of code (in DrRacket):
(let ((x 0))
(define (my-incf y)
(set! x (+ x y)))
(define (my-decf y)
(set! x (- x y))))
it signals a syntax error.
begin (possibly implicit): no expression after a sequence of internal definitions in: (begin (define (my-incf y) (set! x (+ x y))) (define (my-decf y) (set! x (- x y))))
Does anybody know the reason why this cannot be done in Scheme?
Upvotes: 3
Views: 888
Reputation: 8854
Less elegant, but very simple: Define top-level variables, then set!
or setf
them to lambdas from inside the let
, depending on whether it's Scheme or CL.
Upvotes: 0
Reputation: 18917
Chris' solution is what I would use in this case, but here's another one in the spirit of "Let over Lambda" which can come in handy if you increase the number of operations on x:
(define inc-dec
(let ((x 0))
(lambda (msg y)
(case msg
((incf) (set! x (+ x y)))
((decf) (set! x (- x y)))
(else (error "wot?")))
x)))
(inc-dec 'incf 1)
(inc-dec 'incf 1)
(inc-dec 'decf 1)
(inc-dec 'decf 1)
Upvotes: 3
Reputation: 223023
You can't define top-level bindings outside of the top-level, in Scheme. (And inside of a let
is definitely outside of the top-level---what you had, instead, was internal definitions, which are not exported to the top-level.) However, using define-values
, you can still do what you need to do:
(define-values (my-incf my-decf)
(let ((x 0))
(values (lambda (y)
(set! x (+ x y))
x)
(lambda (y)
(set! x (- x y))
x))))
However, you can still use internal definitions, to make your code more readable:
(define-values (my-incf my-decf)
(let ((x 0))
(define (my-incf y)
(set! x (+ x y))
x)
(define (my-decf y)
(set! x (- x y))
x)
(values my-incf my-decf)))
Best of both worlds. :-) In this case, the values
sends the internal my-incf
and my-decf
definitions to the outer define-values
, which is where the real top-level definition happens.
Upvotes: 10