this post was submitted on 10 Oct 2023
0 points (50.0% liked)

Lisp

53 readers
2 users here now

founded 1 year ago
MODERATORS
 

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 ?

top 8 comments
sorted by: hot top controversial new old
[–] [email protected] 1 points 1 year ago (1 children)

Your markdown is making me a sad panda.

[–] [email protected] 1 points 1 year ago (1 children)

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/

[–] [email protected] 1 points 1 year ago
[–] [email protected] 1 points 1 year ago (1 children)

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"]

[–] [email protected] 1 points 1 year ago

Because it's a closure.

[–] [email protected] 1 points 1 year ago

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*).

This

[–] [email protected] 1 points 1 year ago

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.

[–] [email protected] 1 points 1 year ago

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 a lambda. This definition allows you to avoid the funcall:

(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 called incf 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's define does not affect global scope; its effects are only visible locally. This means that a defun inside of a let body still creates a globally accessible function that closes over the variables defined in the let bindings. Scheme, by contrast, needs to have a define at global level (or at least outside the let) but the function body still needs to close over the let variables.