diff --git a/common_lisp/20231123_quote_unquote.html b/common_lisp/20231123_quote_unquote.html new file mode 100644 index 0000000..dc1a8b8 --- /dev/null +++ b/common_lisp/20231123_quote_unquote.html @@ -0,0 +1,84 @@ + +

Quoting and Unquoting in Common Lisp

+

Thursday, Nov 23, 2023

+ +

+ Reading Let Over Lambda (LOL), and in Chapter 3 he demonstrates how to + create macros that will only evaluate a form once. The macro + is defmacro! and on page 60 he gives an example of it's use and + the results. +

+ +
+(defmacro! square (o!x)
+  `(progn
+     (format t "[~a gives ~a]~%")
+         ',o!x ,g!x)
+     (* ,g!x ,g!x))
+
+ +

+ Note the quote-unquote (',) preceding o!x +

+ +

+The thing I have to remember is that macros do not evaluate the forms they are +given, but return forms to be evaluated later. +

+ +

To show how this works, set a variable to a form that is quoted.

+ +
+CL-USER> (defvar b '(+ 1 3))
+(+ 1 3)
+
+ +

The REPL returns the form unevaluated.

+ +

If we use it in an expression, backquote the expression and unquote symbol B, + we will see how it expands. +

+ +
+CL-USER>  `(+ 1 ,b)
+(+ 1 (+ 1 3))
+
+ +

And if we evaluate the above it will return 5.

+ +
+CL-USER>  (eval `(+ 1 ,b))
+5
+
+ +

BUT, if we quote-unquote it, the top-level returns:

+ +
+CL-USER> `(+ 1 ',b)
+(+ 1 '(+ 1 3))
+
+ +

If we were to evaluate the above it would throw us into the debugger because + of '(+ 1 3) +

+ +

+To evaluate it without throwing an error we need to perform two evaluations: +

+ +
+CL-USER> (eval `(+ 1 (eval ',b)))
+5
+
+ +

+This also demonstrates how functions evaluate their arguments first BEFORE they +perform the calculations in defined in the function. +

+ +

+With macros, they do not evaluate their arguments. Macros return forms to be +evaluated later. Thus, when a macro is given an expression (+ 1 3) + it needs to be unquoted in order to be evaluated at a later time (remember when +defining macros everything is wrapped in a backquote). +

diff --git a/common_lisp/named_list_let_over_lambda_functions.html b/common_lisp/named_list_let_over_lambda_functions.html new file mode 100644 index 0000000..ad4e06b --- /dev/null +++ b/common_lisp/named_list_let_over_lambda_functions.html @@ -0,0 +1,110 @@ + +

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. +