Search code examples
lambdaracketlexical-closures

Racket using lexical closures


I read in Let over Lambda about lexical clojures and this code sample was given for Common Lisp:

(let ((counter 0))
  (lambda () (incf counter)))

I tried writing this in Racket as:

(let ((counter 0))
  (lambda() (+ counter 1)))

When I call it in the REPL as counter it gives me the error:

counter: undefined;
 cannot reference an identifier before its definition

As far as I understood, mixing let/set with lambda gives you the ability to store in a lambda some state that can be processed by other functions in the same manner that human memory can be processed and changed by the input from the senses. I'm interested in having in my LISP programs parts of code that are changed by their interaction with other function. Even if this isn't done by lambda, I still want to understand it(the lambda function) because it appears to be an important part of Racket and other LISP dialects.


Solution

  • (incf x) in Common Lisp is not equivalent to (+ x 1) in Racket, but is the combination of first incrementing x: (set! x (+ x 1)), and then returning the new value.

    So, if you want to define a similar function in Racket you could write this, for instance:

    (define count
      (let ((counter 0))
        (lambda () (begin (set! counter (+ counter 1)) counter))))
    
    (count)    ; returns 1
    
    (count)    ; returns 2