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 ?

  • funk443@alien.topB
    link
    fedilink
    English
    arrow-up
    1
    ·
    3 年前

    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

  • Ok_Specific_7749@alien.topBOP
    link
    fedilink
    English
    arrow-up
    1
    ·
    3 年前

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

  • corbasai@alien.topB
    link
    fedilink
    English
    arrow-up
    1
    ·
    3 年前

    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.

  • esgarth@alien.topB
    link
    fedilink
    English
    arrow-up
    1
    ·
    3 年前

    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.