From 570ec471d1605318aeefb030cd78682ae442235b Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Mon, 31 Mar 2025 21:51:40 -0300 Subject: src/content/: Update all files left to asciidoc --- .../tils/2021/04/24/cl-generic-precedence.adoc | 98 ++++++++++++---------- 1 file changed, 55 insertions(+), 43 deletions(-) (limited to 'src/content/tils/2021/04/24/cl-generic-precedence.adoc') 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)) # @@ -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 () ()) # @@ -63,11 +55,13 @@ CLOS uses a similar logic when choosing the method from parent classes, when mul ; Compiling Top-Level Form: # -``` +---- -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) ()) # @@ -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)) # @@ -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)) # * (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 -- cgit v1.2.3