Search code examples
schemeclosuresmutatorslexical-scope

scheme functions that "remember" values with let/set


I'm new to Scheme and trying to understand how certain values that appear within a function can persist across multiple uses. Take the following counter:

(define count
   (let ((next 0))
     (lambda ()
       (let ((v next))
         (set! next (+ next 1))
         v))))

What I can't figure out (and haven't found explained anywhere), is why next doesn't get reset to 0 every time count is used.


Solution

  • I don't totally agree with your explanation. You're right in that the function's definition is evaluated only once, but the function itself is evaluated every time it is called.

    The point I don't agree with is the "...rewrites the definition...", because the function is defined only once (and not explicitly overwritten).

    I imagine it the following way: Due to the so-called lexical binding of variables in scheme, the scheme interpreter notices during the evaluation of the function definition that there's a variable defined in the environment of the function definition - the variable "next". Therefore it remembers not only the function definition, but the value of the variable "next", too (this means that it stores two things - the function definition and the enclosing environment). When the function in called for the first time, its definition is evaluated by the scheme interpreter within the stored environment (in which the variable "next" has the value 0, and were the value is incremented). The second time the function is called, exactly the same things happen - the same function definition is evaluated in its enclosing environment. This time, however, the environment provides the value 1 for the variable "next" and the result of the function call is 1.

    To phrase is concisely: The function (definition) stays the same, it's the evaluation environment that changes.