summaryrefslogtreecommitdiff
path: root/src/content/tils/2021/04/24
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2025-03-31 21:51:40 -0300
committerEuAndreh <eu@euandre.org>2025-03-31 21:51:40 -0300
commit570ec471d1605318aeefb030cd78682ae442235b (patch)
tree51e17eabe37c6689f8799b55e6875c3480329a2c /src/content/tils/2021/04/24
parentMakefile, mkdeps.sh: Derive index.html and feed.xml from more static "sortdat... (diff)
downloadeuandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.gz
euandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.xz
src/content/: Update all files left to asciidoc
Diffstat (limited to 'src/content/tils/2021/04/24')
-rw-r--r--src/content/tils/2021/04/24/cl-generic-precedence.adoc98
-rw-r--r--src/content/tils/2021/04/24/clojure-autocurry.adoc66
-rw-r--r--src/content/tils/2021/04/24/scm-nif.adoc53
3 files changed, 111 insertions, 106 deletions
diff --git a/src/content/tils/2021/04/24/cl-generic-precedence.adoc b/src/content/tils/2021/04/24/cl-generic-precedence.adoc
index 8051232..541afb0 100644
--- a/src/content/tils/2021/04/24/cl-generic-precedence.adoc
+++ b/src/content/tils/2021/04/24/cl-generic-precedence.adoc
@@ -1,20 +1,10 @@
----
+= Common Lisp argument precedence order parameterization of a generic function
-title: Common Lisp argument precedence order parameterization of a generic function
+When CLOS dispatches a method, it picks the most specific method definition to
+the argument list:
-date: 2021-04-24 2
-
-layout: post
-
-lang: en
-
-ref: common-lisp-argument-precedence-order-parameterization-of-a-generic-function
-
----
-
-When CLOS dispatches a method, it picks the most specific method definition to the argument list:
-
-```lisp
+[source,lisp]
+----
* (defgeneric a-fn (x))
#<STANDARD-GENERIC-FUNCTION A-FN (0) {5815ACB9}>
@@ -39,11 +29,13 @@ When CLOS dispatches a method, it picks the most specific method definition to t
* (a-fn 1)
:NUMBER-1
-```
+----
-CLOS uses a similar logic when choosing the method from parent classes, when multiple ones are available:
+CLOS uses a similar logic when choosing the method from parent classes, when
+multiple ones are available:
-```lisp
+[source,lisp]
+----
* (defclass class-a () ())
#<STANDARD-CLASS CLASS-A {583E0B25}>
@@ -63,11 +55,13 @@ CLOS uses a similar logic when choosing the method from parent classes, when mul
; Compiling Top-Level Form:
#<STANDARD-METHOD ANOTHER-FN (CLASS-B) {584B8895}>
-```
+----
-Given the above definitions, when inheriting from `class-a` and `class-b`, the order of inheritance matters:
+Given the above definitions, when inheriting from `class-a` and `class-b`, the
+order of inheritance matters:
-```lisp
+[source,lisp]
+----
* (defclass class-a-coming-first (class-a class-b) ())
#<STANDARD-CLASS CLASS-A-COMING-FIRST {584BE6AD}>
@@ -79,11 +73,14 @@ Given the above definitions, when inheriting from `class-a` and `class-b`, the o
* (another-fn (make-instance 'class-b-coming-first))
:CLASS-B
-```
+----
-Combining the order of inheritance with generic functions with multiple arguments, CLOS has to make a choice of how to pick a method given two competing definitions, and its default strategy is prioritizing from left to right:
+Combining the order of inheritance with generic functions with multiple
+arguments, CLOS has to make a choice of how to pick a method given two competing
+definitions, and its default strategy is prioritizing from left to right:
-```lisp
+[source,lisp]
+----
* (defgeneric yet-another-fn (obj1 obj2))
#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (0) {584D9EC9}>
@@ -95,43 +92,58 @@ Combining the order of inheritance with generic functions with multiple argument
* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))
:FIRST-ARG-SPECIALIZED
-```
+----
-CLOS has to make a choice between the first and the second definition of `yet-another-fn`, but its choice is just a heuristic.
-What if we want the choice to be based on the second argument, instead of the first?
+CLOS has to make a choice between the first and the second definition of
+`yet-another-fn`, but its choice is just a heuristic. What if we want the
+choice to be based on the second argument, instead of the first?
-For that, we use the `:argument-precedence-order` option when declaring a generic function:
+For that, we use the `:argument-precedence-order` option when declaring a
+generic function:
-```lisp
+[source,lisp]
+----
* (defgeneric yet-another-fn (obj1 obj2) (:argument-precedence-order obj2 obj1))
#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (2) {584D9EC9}>
* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))
:SECOND-ARG-SPECIALIZED
-```
+----
-I liked that the `:argument-precedence-order` option exists.
-We shouldn't have to change the arguments from `(obj1 obj2)` to `(obj2 obj1)` just to make CLOS pick the method that we want.
-We can configure its default behaviour if desired, and keep the order of arguments however it best fits the generic function.
+I liked that the `:argument-precedence-order` option exists. We shouldn't have
+to change the arguments from `(obj1 obj2)` to `(obj2 obj1)` just to make CLOS
+pick the method that we want. We can configure its default behaviour if
+desired, and keep the order of arguments however it best fits the generic
+function.
-## Comparison with Clojure
+== Comparison with Clojure
Clojure has an equivalent, when using `defmulti`.
-Since when declaring a multi-method with `defmulti` we must define the dispatch function, Clojure uses it to pick the method definition.
-Since the dispatch function is required, there is no need for a default behaviour, such as left-to-right.
+Since when declaring a multi-method with `defmulti` we must define the dispatch
+function, Clojure uses it to pick the method definition. Since the dispatch
+function is required, there is no need for a default behaviour, such as
+left-to-right.
-## Conclusion
+== Conclusion
-Making the argument precedence order configurable for generic functions but not for class definitions makes a lot of sense.
+Making the argument precedence order configurable for generic functions but not
+for class definitions makes a lot of sense.
-When declaring a class, we can choose the precedence order, and that is about it.
-But when defining a generic function, the order of arguments is more important to the function semantics, and the argument precedence being left-to-right is just the default behaviour.
+When declaring a class, we can choose the precedence order, and that is about
+it. But when defining a generic function, the order of arguments is more
+important to the function semantics, and the argument precedence being
+left-to-right is just the default behaviour.
-One shouldn't change the order of arguments of a generic function for the sake of tailoring it to the CLOS priority ranking algorithm, but doing it for a class definition is just fine.
+One shouldn't change the order of arguments of a generic function for the sake
+of tailoring it to the CLOS priority ranking algorithm, but doing it for a class
+definition is just fine.
TIL.
-## References
+== References
+
+:clos-wiki: https://en.wikipedia.org/wiki/Object-Oriented_Programming_in_Common_Lisp
-1. [Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS](https://en.wikipedia.org/wiki/Object-Oriented_Programming_in_Common_Lisp), by Sonja E. Keene
+. {clos-wiki}[Object-Oriented Programming in Common Lisp: A Programmer's Guide
+ to CLOS], by Sonja E. Keene
diff --git a/src/content/tils/2021/04/24/clojure-autocurry.adoc b/src/content/tils/2021/04/24/clojure-autocurry.adoc
index c1e277f..d7dd557 100644
--- a/src/content/tils/2021/04/24/clojure-autocurry.adoc
+++ b/src/content/tils/2021/04/24/clojure-autocurry.adoc
@@ -1,22 +1,13 @@
----
+= Clojure auto curry
-title: Clojure auto curry
+:defcurry-orig: https://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry
-date: 2021-04-24 1
+Here's a simple macro defined by {defcurry-orig}[Loretta He] to create Clojure
+functions that are curried on all arguments, relying on Clojure's multi-arity
+support:
-updated_at: 2021-04-27
-
-layout: post
-
-lang: en
-
-ref: clojure-auto-curry
-
----
-
-Here's a simple macro defined by [Loretta He][lorettahe] to create Clojure functions that are curried on all arguments, relying on Clojure's multi-arity support:
-
-```clojure
+[source,clojure]
+----
(defmacro defcurry
[name args & body]
(let [partials (map (fn [n]
@@ -25,11 +16,12 @@ Here's a simple macro defined by [Loretta He][lorettahe] to create Clojure funct
`(defn ~name
(~args ~@body)
~@partials)))
-```
+----
A naive `add` definition, alongside its usage and macroexpansion:
-```clojure
+[source,clojure]
+----
user=> (defcurry add
[a b c d e]
(+ 1 2 3 4 5))
@@ -64,22 +56,24 @@ user=> (pprint
([a b c] (clojure.core/partial add a b c))
([a b c d] (clojure.core/partial add a b c d))))
nil
-```
+----
-This simplistic `defcurry` definition doesn't support optional parameters, multi-arity, `&` rest arguments, docstrings, etc., but it could certainly evolve to do so.
+This simplistic `defcurry` definition doesn't support optional parameters,
+multi-arity, `&` rest arguments, docstrings, etc., but it could certainly evolve
+to do so.
-I like how `defcurry` is so short, and abdicates the responsability of doing the multi-arity logic to Clojure's built-in multi-arity support.
-Simple and elegant.
+I like how `defcurry` is so short, and abdicates the responsability of doing the
+multi-arity logic to Clojure's built-in multi-arity support. Simple and
+elegant.
Same Clojure as before, now with auto-currying via macros.
-[lorettahe]: http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry
-
-## Comparison with Common Lisp
+== Comparison with Common Lisp
My attempt at writing an equivalent for Common Lisp gives me:
-```lisp
+[source,lisp]
+----
(defun partial (fn &rest args)
(lambda (&rest args2)
(apply fn (append args args2))))
@@ -96,15 +90,17 @@ My attempt at writing an equivalent for Common Lisp gives me:
(let ((func (lambda ,args ,@body)))
(curry-n (- ,(length args) (length rest))
(apply #'partial func rest)))))
-```
+----
-Without built-in multi-arity support, we have to do more work, like tracking the number of arguments consumed so far.
-We also have to write `#'partial` ourselves.
-That is, without dependending on any library, sticking to ANSI Common Lisp.
+Without built-in multi-arity support, we have to do more work, like tracking the
+number of arguments consumed so far. We also have to write `#'partial`
+ourselves. That is, without dependending on any library, sticking to ANSI
+Common Lisp.
The usage is pretty similar:
-```lisp
+[source,lisp]
+----
* (defcurry add (a b c d e)
(+ a b c d e))
ADD
@@ -128,8 +124,10 @@ ADD
(LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E))))
(CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST))))
T
-```
+----
-This also require `funcall`s, since we return a `lambda` that doesn't live in the function namespace.
+This also require `funcall`s, since we return a `lambda` that doesn't live in
+the function namespace.
-Like the Clojure one, it doesn't support optional parameters, `&rest` rest arguments, docstrings, etc., but it also could evolve to do so.
+Like the Clojure one, it doesn't support optional parameters, `&rest` rest
+arguments, docstrings, etc., but it also could evolve to do so.
diff --git a/src/content/tils/2021/04/24/scm-nif.adoc b/src/content/tils/2021/04/24/scm-nif.adoc
index f53451b..f70e533 100644
--- a/src/content/tils/2021/04/24/scm-nif.adoc
+++ b/src/content/tils/2021/04/24/scm-nif.adoc
@@ -1,35 +1,28 @@
----
+= Three-way conditional for number signs on Lisp
-title: Three-way conditional for number signs on Lisp
+:on-lisp: https://www.paulgraham.com/onlisptext.html
+:sicp: https://mitpress.mit.edu/sites/default/files/sicp/index.html
-date: 2021-04-24 3
+A useful macro from Paul Graham's {on-lisp}[On Lisp] book:
-updated_at: 2021-08-14
-
-layout: post
-
-lang: en
-
-ref: three-way-conditional-for-number-signs-on-lisp
-
----
-
-A useful macro from Paul Graham's [On Lisp][on-lisp] book:
-
-```lisp
+[source,lisp]
+----
(defmacro nif (expr pos zero neg)
(let ((g (gensym)))
`(let ((,g ,expr))
(cond ((plusp ,g) ,pos)
((zerop ,g) ,zero)
(t ,neg)))))
-```
+----
-After I looked at this macro, I started seeing opportunities to using it in many places, and yet I didn't see anyone else using it.
+After I looked at this macro, I started seeing opportunities to using it in many
+places, and yet I didn't see anyone else using it.
-The latest example I can think of is section 1.3.3 of [Structure and Interpretation of Computer Programs][sicp], which I was reading recently:
+The latest example I can think of is section 1.3.3 of {sicp}[Structure and
+Interpretation of Computer Programs], which I was reading recently:
-```scheme
+[source,scheme]
+----
(define (search f neg-point pos-point)
(let ((midpoint (average neg-point pos-point)))
(if (close-enough? neg-point post-point)
@@ -40,11 +33,14 @@ The latest example I can think of is section 1.3.3 of [Structure and Interpretat
((negative? test-value)
(search f midpoint pos-point))
(else midpoint))))))
-```
+----
-Not that the book should introduce such macro this early, but I couldn't avoid feeling bothered by not using the `nif` macro, which could even remove the need for the intermediate `test-value` variable:
+Not that the book should introduce such macro this early, but I couldn't avoid
+feeling bothered by not using the `nif` macro, which could even remove the need
+for the intermediate `test-value` variable:
-```scheme
+[source,scheme]
+----
(define (search f neg-point pos-point)
(let ((midpoint (average neg-point pos-point)))
(if (close-enough? neg-point post-point)
@@ -53,11 +49,10 @@ Not that the book should introduce such macro this early, but I couldn't avoid f
(search f neg-point midpoint)
(midpoint)
(search f midpoint pos-point)))))
-```
-
-It also avoids `cond`'s extra clunky parentheses for grouping, which is unnecessary but built-in.
+----
-As a macro, I personally feel it tilts the balance towards expressivenes despite its extra cognitive load toll.
+It also avoids `cond`'s extra clunky parentheses for grouping, which is
+unnecessary but built-in.
-[on-lisp]: http://www.paulgraham.com/onlisptext.html
-[sicp]: https://mitpress.mit.edu/sites/default/files/sicp/index.html
+As a macro, I personally feel it tilts the balance towards expressivenes despite
+its extra cognitive load toll.