Named Functions From A List of Let Over Lambda Functions

Sunday, Nov 18, 2023

Let Over Lambda presents a LoL that returns a list of lambda functions for a counter variable. Somewhere around pg 32, maybe.

(let ((counter 0))
  (values
     (lamda () (incf counter))
     (lamda () (decf counter))))

That got me wondering how to access the values returned. I first tried (setf a ( ... )) but it only gave me the first value,

(incf counter)

I tried multiple-bind-values but read that the variables assigned the functions were only accessible within the multiple-bind-values binding. (Source ?? )

I finally settled on:

(setf a (multiple-value-list
  (let ((counter 0))
     (values
        (lambda () (incf counter))
        (lambda () (decf counter))
        (lambda () counter)))))

Then, assign each to value from the list to a variable, like this:

(defun increase-count ()
   (funcall (car a)))

(defun decrease-count ()
   (funcall (nth 1 a)))

(defun get-count ()
   (funcall (nth 2 a)))

LoL, states that the let over lamda is essentially an object, no different from a an object returned by a class. And it is true. If I rewrite

(set a
    (...))
as a function like this:

(defun counter-class (multiple-value-list
  (let ((counter 0))
     (values
        (lambda () (incf counter))
        (lambda () (decf counter))
        (lambda () counter)))))

Then I can define two player count objects: player1 and player2

(defun player1 () (counter-class))

(defun player2 () (counter-class))

Now, to call each function within respective players object, I can write this:

(funcall (car player1))     ; to increase player 1
(funcall (nth 1 player1))   ; to decrease count for player 1
(funcall (nth 2 player1))   ; to return the current value of count for player1

And of course I could do the same for player 2

But this is kind of ugly so I could create functions for each player

(defun player1.incf ()
   (funcall (car player1)))

(defun player1.decf ()
   (funcall (nth 1 player1)))

(defun player1.get ()
   (funcall (nth 2 player1)))

I would have to do the same for player2, which would be kind of tedious.

According to Graham and Hoyte, copying code begs to be made into a macro. Which I will return to later once I have a better understanding of how to write macros.