A counter in racket-scheme:
#lang typed/racket
(define my-counter!
(let ([t 0])
(lambda ()
(set! t (+ 1 t))
t);lambda
);let
);define
(print (my-counter!))
(print (my-counter!))
A counter in sbcl-lisp:
load "~/quicklisp/setup.lisp")
(declaim (optimize (speed 3) (safety 3)))
(let ((c 0))
(defun my-counter! ()
(lambda ()
(setf c (+ 1 c))
c); lambda
) ;defun
) ;let
(defun main ()
(print (funcall (my-counter!)))
(print (funcall (my-counter!)))
)
(sb-ext:save-lisp-and-die "test.exe" :toplevel #'main :executable t)
Could someone elaborate why i need “funcall” in lisp and not in scheme ? And why the different placing of let ?
In Common Lisp, as opposed to Scheme, it is not possible that the car of the compound form to be evaluated is an arbitrary form. If it is not a symbol, it must be a lambda expression, which looks like (lambda lambda-list form*).
Why must the variable c be declared outside and before the function definition my-counter!.
[ If you put it inside the value is always “reset”]Because it’s a closure.
Your markdown is making me a sad panda.
Are you on old reddit by chance?
For the youngsters: The tripple ` notation doesn’t work on old reddit. Indent each line of code with four spaces.
https://old.reddit.com/r/scheme/comments/16y3avr/comparison_of_a_counter_in_racketscheme_and/
Sure am!
funcall isn’t needed, because in your snippet defun-ed f.
funcall for defvar lambdas in CL.
Scheme is a Lisp-1 -> variables and procedures are defined in one namespace.
In CL (Lisp-2) variables and functions separated.
You shouldn’t need
funcall
in your common lisp code, but the way you defined your function requires it. You have(let ((c 0)) (defun my-counter! () (lambda () (setf c (+ 1 c)) c)))
defun
already defines a function; you don’t need to also wrap the function body in alambda
. This definition allows you to avoid thefuncall
:(let ((c 0)) (defun my-counter! () (setf c (+ 1 c)) c))
Though it’s worth knowing that unlike in scheme, common lisp will return the value after a
setf
. There’s also a convenience macro calledincf
that increments variables so you can write the whole thing like this:(let ((c 0)) (defun my-counter! () (incf c)))
And your other question: Why the different placing of the let?
In common lisp,
defun
,defvar
,defparameter
,defmacro
, … all affect global scope, no matter where they appear. scheme’sdefine
does not affect global scope; its effects are only visible locally. This means that adefun
inside of alet
body still creates a globally accessible function that closes over the variables defined in thelet
bindings. Scheme, by contrast, needs to have adefine
at global level (or at least outside thelet
) but the function body still needs to close over thelet
variables.