aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.md4
-rw-r--r--_articles/2021-04-29-a-relational-model-of-data-for-large-shared-data-banks-article-review.md130
-rw-r--r--_pastebins/2021-04-03-javascript-naive-slugify.md34
-rw-r--r--_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md2
-rw-r--r--_tils/2021-04-24-clojure-auto-curry.md135
-rw-r--r--_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.md137
-rw-r--r--_tils/2021-04-24-three-way-conditional-for-number-signs.md61
-rwxr-xr-xaux/workflow/public.sh2
-rw-r--r--default.nix101
-rw-r--r--locale/eo/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po4
-rw-r--r--locale/eo/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po14
-rw-r--r--locale/eo/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po10
-rw-r--r--locale/eo/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po57
-rw-r--r--locale/eo/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po70
-rw-r--r--locale/eo/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po24
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po9
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po6
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po220
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po210
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po95
-rw-r--r--locale/fr/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po4
-rw-r--r--locale/fr/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po14
-rw-r--r--locale/fr/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po10
-rw-r--r--locale/fr/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po57
-rw-r--r--locale/fr/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po70
-rw-r--r--locale/fr/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po24
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po9
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po6
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po220
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po210
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po95
-rw-r--r--locale/pt/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po4
-rw-r--r--locale/pt/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po14
-rw-r--r--locale/pt/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po10
-rw-r--r--locale/pt/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po57
-rw-r--r--locale/pt/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po70
-rw-r--r--locale/pt/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po24
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po9
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po6
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po220
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po210
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po95
42 files changed, 2500 insertions, 263 deletions
diff --git a/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.md b/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.md
index 7bb4356..0add24e 100644
--- a/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.md
+++ b/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.md
@@ -152,8 +152,8 @@ void *fallible_malloc(size_t size, const char *const filename, int lineno) {
With this definition, I could replace the calls to `malloc` with `MALLOC` (or any other name that you want to `#define`):
```diff
---- 3.c 2021-02-17 00:15:38.019706074 -0300
-+++ 4.c 2021-02-17 00:44:32.306885590 -0300
+--- 3.c 2021-02-17 00:15:38.019706074 -0300
++++ 4.c 2021-02-17 00:44:32.306885590 -0300
@@ -1,11 +1,11 @@
bool a_function() {
- char *s1 = malloc(A_NUMBER);
diff --git a/_articles/2021-04-29-a-relational-model-of-data-for-large-shared-data-banks-article-review.md b/_articles/2021-04-29-a-relational-model-of-data-for-large-shared-data-banks-article-review.md
new file mode 100644
index 0000000..e15b478
--- /dev/null
+++ b/_articles/2021-04-29-a-relational-model-of-data-for-large-shared-data-banks-article-review.md
@@ -0,0 +1,130 @@
+---
+
+title: A Relational Model of Data for Large Shared Data Banks - article-review
+
+date: 2021-04-29
+
+layout: post
+
+lang: en
+
+ref: a-relational-model-of-data-for-large-shared-data-banks-article-review
+
+---
+
+This is a review of the article "[A Relational Model of Data for Large Shared Data Banks][codd-article]", by E. F. Codd.
+
+[codd-article]: https://www.seas.upenn.edu/~zives/03f/cis550/codd.pdf
+
+## Data Independence
+
+Codd brings the idea of *data independence* as a better approach to use on databases.
+This is contrast with the existing approaches, namely hierarquical (tree-based) and network-based.
+
+His main argument is that queries in applications shouldn't depende and be coupled with how the data is represented internally by the database system.
+This key idea is very powerful, and something that we strive for in many other places: decoupling the interface from the implementation.
+
+If the database system has this separation, it can kep the querying interface stable, while having the freedom to change its internal representation at will, for better performance, less storage, etc.
+
+This is true for most modern database systems.
+They can change from B-Trees with leafs containing pointers to data, to B-Trees with leafs containing the raw data , to hash tables.
+All that without changing the query interface, only its performance.
+
+Codd mentions that, from an information representation standpoint, any index is a duplication, but useful for perfomance.
+
+This data independence also impacts ordering (a *relation* doesn't rely on the insertion order).
+
+## Duplicates
+
+His definition of relational data is a bit differente from most modern database systems, namely **no duplicate rows**.
+
+I couldn't find a reason behind this restriction, though.
+For practical purposes, I find it useful to have it.
+
+## Relational Data
+
+In the article, Codd doesn't try to define a language, and today's most popular one is SQL.
+
+However, there is no restriction that says that "SQL database" and "relational database" are synonyms.
+One could have a relational database without using SQL at all, and it would still be a relational one.
+
+The main one that I have in mind, and the reason that led me to reading this paper in the first place, is Datomic.
+
+Is uses an [edn]-based representation for datalog queries[^edn-queries], and a particular schema used to represent data.
+
+Even though it looks very weird when coming from SQL, I'd argue that it ticks all the boxes (except for "no duplicates") that defines a relational database, since building relations and applying operations on them is possible.
+
+Compare and contrast a contrived example of possible representations of SQL and datalog of the same data:
+
+```sql
+-- create schema
+CREATE TABLE people (
+ id UUID PRIMARY KEY,
+ name TEXT NOT NULL,
+ manager_id UUID,
+ FOREIGN KEY (manager_id) REFERENCES people (id)
+);
+
+-- insert data
+INSERT INTO people (id, name, manager_id) VALUES
+ ("d3f29960-ccf0-44e4-be66-1a1544677441", "Foo", "076356f4-1a0e-451c-b9c6-a6f56feec941"),
+ ("076356f4-1a0e-451c-b9c6-a6f56feec941", "Bar");
+
+-- query data, make a relation
+
+SELECT employees.name AS 'employee-name',
+ managers.name AS 'manager-name'
+FROM people employees
+INNER JOIN people managers ON employees.manager_id = managers.id;
+```
+
+{% raw %}
+```
+;; create schema
+#{ {:db/ident :person/id
+ :db/valueType :db.type/uuid
+ :db/cardinality :db.cardinality/one
+ :db/unique :db.unique/value}
+ {:db/ident :person/name
+ :db/valueType :db.type/string
+ :db/cardinality :db.cardinality/one}
+ {:db/ident :person/manager
+ :db/valueType :db.type/ref
+ :db/cardinality :db.cardinality/one}}
+
+;; insert data
+#{ {:person/id #uuid "d3f29960-ccf0-44e4-be66-1a1544677441"
+ :person/name "Foo"
+ :person/manager [:person/id #uuid "076356f4-1a0e-451c-b9c6-a6f56feec941"]}
+ {:person/id #uuid "076356f4-1a0e-451c-b9c6-a6f56feec941"
+ :person/name "Bar"}}
+
+;; query data, make a relation
+{:find [?employee-name ?manager-name]
+ :where [[?person :person/name ?employee-name]
+ [?person :person/manager ?manager]
+ [?manager :person/name ?manager-name]]}
+```
+{% endraw %}
+
+(forgive any errors on the above SQL and datalog code, I didn't run them to check. Patches welcome!)
+
+This employee example comes from the paper, and both SQL and datalog representations match the paper definition of "relational".
+
+Both "Foo" and "Bar" are employees, and the data is normalized.
+SQL represents data as tables, and Datomic as datoms, but relations could be derived from both, which we could view as:
+
+```
+employee_name | manager_name
+----------------------------
+"Foo" | "Bar"
+```
+
+[^edn-queries]: You can think of it as JSON, but with a Clojure taste.
+[edn]: https://github.com/edn-format/edn
+
+## Conclusion
+
+The article also talks about operators, consistency and normalization, which are now so widespread and well-known that it feels a bit weird seeing someone advocating for it.
+
+I also stablish that `relational != SQL`, and other databases such as Datomic are also relational, following Codd's original definition.
diff --git a/_pastebins/2021-04-03-javascript-naive-slugify.md b/_pastebins/2021-04-03-javascript-naive-slugify.md
index 05251c7..ce038fd 100644
--- a/_pastebins/2021-04-03-javascript-naive-slugify.md
+++ b/_pastebins/2021-04-03-javascript-naive-slugify.md
@@ -16,23 +16,23 @@ ref: javascript-naive-slugify
const s = "Pézão: açaí, saci-pererê.";
function slugify(s) {
- return s
- .toLowerCase()
- .replaceAll(":", "")
- .replaceAll(".", "")
- .replaceAll(",", "")
- .replaceAll("-", "")
- .replaceAll("á", "a")
- .replaceAll("ã", "a")
- .replaceAll("à", "a")
- .replaceAll("é", "e")
- .replaceAll("ê", "e")
- .replaceAll("í", "i")
- .replaceAll("ó", "o")
- .replaceAll("ô", "o")
- .replaceAll("ú", "u")
- .replaceAll("ü", "u")
- .replaceAll("ç", "c");
+ return s
+ .toLowerCase()
+ .replaceAll(":", "")
+ .replaceAll(".", "")
+ .replaceAll(",", "")
+ .replaceAll("-", "")
+ .replaceAll("á", "a")
+ .replaceAll("ã", "a")
+ .replaceAll("à", "a")
+ .replaceAll("é", "e")
+ .replaceAll("ê", "e")
+ .replaceAll("í", "i")
+ .replaceAll("ó", "o")
+ .replaceAll("ô", "o")
+ .replaceAll("ú", "u")
+ .replaceAll("ü", "u")
+ .replaceAll("ç", "c");
}
console.log(slugify(s));
diff --git a/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md b/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md
index 7965d29..d06f0c1 100644
--- a/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md
+++ b/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.md
@@ -77,7 +77,7 @@ After any of those checkouts, you have to `git reset .` to reset your current
staging area back to what it was before the checkout.
-## References:
+## References
1. [GIT: Checkout to a specific folder][0] (StackOverflow)
diff --git a/_tils/2021-04-24-clojure-auto-curry.md b/_tils/2021-04-24-clojure-auto-curry.md
new file mode 100644
index 0000000..c1e277f
--- /dev/null
+++ b/_tils/2021-04-24-clojure-auto-curry.md
@@ -0,0 +1,135 @@
+---
+
+title: Clojure auto curry
+
+date: 2021-04-24 1
+
+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
+(defmacro defcurry
+ [name args & body]
+ (let [partials (map (fn [n]
+ `(~(subvec args 0 n) (partial ~name ~@(take n args))))
+ (range 1 (count args)))]
+ `(defn ~name
+ (~args ~@body)
+ ~@partials)))
+```
+
+A naive `add` definition, alongside its usage and macroexpansion:
+
+```clojure
+user=> (defcurry add
+ [a b c d e]
+ (+ 1 2 3 4 5))
+#'user/add
+
+user=> (add 1)
+#object[clojure.core$partial$fn__5857 0x2c708440 "clojure.core$partial$fn__5857@2c708440"]
+
+user=> (add 1 2 3 4)
+#object[clojure.core$partial$fn__5863 0xf4c0e4e "clojure.core$partial$fn__5863@f4c0e4e"]
+
+user=> ((add 1) 2 3 4 5)
+15
+
+user=> (((add 1) 2 3) 4 5)
+15
+
+user=> (use 'clojure.pprint)
+nil
+
+user=> (pprint
+ (macroexpand
+ '(defcurry add
+ [a b c d e]
+ (+ 1 2 3 4 5))))
+(def
+ add
+ (clojure.core/fn
+ ([a b c d e] (+ 1 2 3 4 5))
+ ([a] (clojure.core/partial add a))
+ ([a b] (clojure.core/partial add a b))
+ ([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.
+
+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
+
+My attempt at writing an equivalent for Common Lisp gives me:
+
+```lisp
+(defun partial (fn &rest args)
+ (lambda (&rest args2)
+ (apply fn (append args args2))))
+
+(defun curry-n (n func)
+ (cond ((< n 0) (error "Too many arguments"))
+ ((zerop n) (funcall func))
+ (t (lambda (&rest rest)
+ (curry-n (- n (length rest))
+ (apply #'partial func rest))))))
+
+(defmacro defcurry (name args &body body)
+ `(defun ,name (&rest rest)
+ (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.
+
+The usage is pretty similar:
+
+```lisp
+* (defcurry add (a b c d e)
+ (+ a b c d e))
+ADD
+
+* (add 1)
+#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216419B}>
+
+* (funcall (add 1) 2 3 4)
+#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216537B}>
+
+* (funcall (add 1) 2 3 4 5)
+15
+
+* (funcall (funcall (add 1) 2 3) 4 5)
+15
+
+* (macroexpand-1
+ '(defcurry add (a b c d e)
+ (+ a b c d e)))
+(DEFUN ADD (&REST REST)
+ (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.
+
+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/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.md b/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.md
new file mode 100644
index 0000000..8051232
--- /dev/null
+++ b/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.md
@@ -0,0 +1,137 @@
+---
+
+title: Common Lisp argument precedence order parameterization of a generic function
+
+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
+
+* (defgeneric a-fn (x))
+#<STANDARD-GENERIC-FUNCTION A-FN (0) {5815ACB9}>
+
+* (defmethod a-fn (x) :default-method)
+#<STANDARD-METHOD A-FN (T) {581DB535}>
+
+* (defmethod a-fn ((x number)) :a-number)
+#<STANDARD-METHOD A-FN (NUMBER) {58241645}>
+
+* (defmethod a-fn ((x (eql 1))) :number-1)
+#<STANDARD-METHOD A-FN ((EQL 1)) {582A7D75}>
+
+* (a-fn nil)
+:DEFAULT-METHOD
+
+* (a-fn "1")
+:DEFAULT-METHOD
+
+* (a-fn 0)
+:A-NUMBER
+
+* (a-fn 1)
+:NUMBER-1
+```
+
+CLOS uses a similar logic when choosing the method from parent classes, when multiple ones are available:
+
+```lisp
+* (defclass class-a () ())
+
+#<STANDARD-CLASS CLASS-A {583E0B25}>
+* (defclass class-b () ())
+
+#<STANDARD-CLASS CLASS-B {583E7F6D}>
+* (defgeneric another-fn (obj))
+
+#<STANDARD-GENERIC-FUNCTION ANOTHER-FN (0) {583DA749}>
+* (defmethod another-fn ((obj class-a)) :class-a)
+; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):
+; Compiling Top-Level Form:
+
+#<STANDARD-METHOD ANOTHER-FN (CLASS-A) {584523C5}>
+* (defmethod another-fn ((obj class-b)) :class-b)
+; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):
+; 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:
+
+```lisp
+* (defclass class-a-coming-first (class-a class-b) ())
+#<STANDARD-CLASS CLASS-A-COMING-FIRST {584BE6AD}>
+
+* (defclass class-b-coming-first (class-b class-a) ())
+#<STANDARD-CLASS CLASS-B-COMING-FIRST {584C744D}>
+
+* (another-fn (make-instance 'class-a-coming-first))
+:CLASS-A
+
+* (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:
+
+```lisp
+* (defgeneric yet-another-fn (obj1 obj2))
+#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (0) {584D9EC9}>
+
+* (defmethod yet-another-fn ((obj1 class-a) obj2) :first-arg-specialized)
+#<STANDARD-METHOD YET-ANOTHER-FN (CLASS-A T) {5854269D}>
+
+* (defmethod yet-another-fn (obj1 (obj2 class-b)) :second-arg-specialized)
+#<STANDARD-METHOD YET-ANOTHER-FN (T CLASS-B) {585AAAAD}>
+
+* (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?
+
+For that, we use the `:argument-precedence-order` option when declaring a generic function:
+
+```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.
+
+## 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.
+
+## Conclusion
+
+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.
+
+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
+
+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
diff --git a/_tils/2021-04-24-three-way-conditional-for-number-signs.md b/_tils/2021-04-24-three-way-conditional-for-number-signs.md
new file mode 100644
index 0000000..ec62378
--- /dev/null
+++ b/_tils/2021-04-24-three-way-conditional-for-number-signs.md
@@ -0,0 +1,61 @@
+---
+
+title: Three-way conditional for number signs
+
+date: 2021-04-24 3
+
+layout: post
+
+lang: en
+
+ref: three-way-conditional-for-number-signs
+
+---
+
+A useful macro from Paul Graham's [On Lisp][on-lisp] book:
+
+```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.
+
+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:
+
+```scheme
+(define (search f neg-point pos-point)
+ (let ((midpoint (average neg-point pos-point)))
+ (if (close-enough? neg-point post-point)
+ midpoint
+ (let ((test-value (f midpoint)))
+ (cond ((positive? test-value)
+ (search f neg-point midpoint))
+ ((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:
+
+```scheme
+(define (search f neg-point pos-point)
+ (let ((midpoint (average neg-point pos-point)))
+ (if (close-enough? neg-point post-point)
+ midpoint
+ (nif (f midpoint)
+ (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.
+
+[on-lisp]: http://www.paulgraham.com/onlisptext.html
+[sicp]: https://mitpress.mit.edu/sites/default/files/sicp/index.html
diff --git a/aux/workflow/public.sh b/aux/workflow/public.sh
index 8ecb855..853583c 100755
--- a/aux/workflow/public.sh
+++ b/aux/workflow/public.sh
@@ -9,7 +9,7 @@ sh aux/workflow/TODOs.sh "$PROJECT_UC" "$PROJECT" "$MAILING_LIST"
sh aux/workflow/commonmark.sh "$PROJECT" README.md index.html ||:
if [ -f CHANGELOG.md ]; then
- sh aux/workflow/commonmark.sh "$PROJECT" CHANGELOG.md
+ sh aux/workflow/commonmark.sh "$PROJECT" CHANGELOG.md
fi
sh aux/ci/report.sh "$PROJECT"
diff --git a/default.nix b/default.nix
deleted file mode 100644
index 2684cea..0000000
--- a/default.nix
+++ /dev/null
@@ -1,101 +0,0 @@
-let
- niv-sources = import ./nix/sources.nix;
- pkgs = import niv-sources.nixpkgs { };
- src = pkgs.nix-gitignore.gitignoreSourcePure [
- "/result*"
- "/_site/"
- "/public/"
- "/.jekyll-cache/"
- ] ./.;
- utils-i18n = pkgs.callPackage ./nix/utils-i18n.nix { };
- pkgs-next = pkgs.callPackage ./nix/nixpkgs-next.nix { };
-
- jekyllEnv = pkgs.bundlerEnv {
- name = "jekyll-env";
- gemfile = ./Gemfile;
- lockfile = ./Gemfile.lock;
- gemset = ./nix/gemset.nix;
- };
-
- mktorrent-newer = pkgs.mktorrent.overrideAttrs (oldAttrs: {
- src = pkgs.fetchFromGitHub {
- owner = "Rudde";
- repo = "mktorrent";
- rev = "ea1fbf29d19f34a93f7d984c1ac29d6d08f1f508";
- sha256 = "1cjq96qridpvqhphj3ljnhysnqkdck415wxaqy768r0rvzqq1ja4";
- };
- });
-
- buildInputs = with pkgs; [
- jekyllEnv
- pkgs-next.mdpo
- mktorrent-newer
- ffmpeg
- flac
- mediainfo
- mkvtoolnix-cli
- inkscape
- imagemagick
-
- pandoc
- gettext
- perl
- graphviz
- nixfmt
- git
- gitAndTools.git-annex
- shellcheck
- jq
- niv
- (hunspellWithDicts (with utils-i18n.dicts; [ en pt fr eo ]))
- ];
- drv = name: buildPhase:
- pkgs.stdenv.mkDerivation {
- inherit src buildInputs buildPhase;
- name = "website-${name}";
- phases = [ "unpackPhase" "buildPhase" ];
- };
-in rec {
- site = drv "site" ''
- make public
- mv public $out
- '';
- test = drv "test" ''
- make check
- touch $out
- '';
- shell = pkgs.mkShell {
- inherit buildInputs;
- name = "website-shell";
- shellHook = ''
- echo 'Starting a live server with:'
- echo ' jekyll serve --future --livereload --trace'
- echo 'Server with feature flags:'
- echo ' jekyll serve --future --livereload --trace -c $(cfg podcast music)'
-
- export JEKYLL_ENV=production
-
- cfg() {
- T="$(mktemp --suffix .yml)"
- cp _config.yml "$T"
- printf '\nflags:' >> "$T"
- for flag in "$@"; do
- printf '\n %s: true' "$flag" >> "$T"
- done
- echo "$T"
- }
- '';
- };
- publishScript = pkgs.writeShellScriptBin "publish.sh" ''
- set -eux
- SERVER_URL='euandre.org'
- REMOTE_PATH='/home/user-data/www/default/'
- OUT_DOCS='${site}'
- ${pkgs.openssh}/bin/ssh "$SERVER_URL" rm -rf "$REMOTE_PATH/*"
- ${pkgs.rsync}/bin/rsync -avzP \
- --rsh="ssh -o StrictHostKeyChecking=no" \
- "$OUT_DOCS/" \
- "$SERVER_URL:$REMOTE_PATH" \
- --delete
- '';
-}
diff --git a/locale/eo/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po b/locale/eo/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
index 86c8389..3c7e6ec 100644
--- a/locale/eo/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
+++ b/locale/eo/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
@@ -12,8 +12,8 @@ msgstr ""
msgid ""
"I wrote a simple little tool called "
-"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick"
-" Swift's package manager into assuming everything is set up. Here's the "
+"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick "
+"Swift's package manager into assuming everything is set up. Here's the "
"example from swift2nix's README file:"
msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po b/locale/eo/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
index 0e0bc8c..ecd28a5 100644
--- a/locale/eo/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
+++ b/locale/eo/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
@@ -381,18 +381,18 @@ msgstr ""
#~ msgid ""
#~ "I've started a fork of cbindgen: "
-#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just "
-#~ "a copy of cbindgen verbatim, and I plan to remove all C and C++ emitting "
-#~ "code from it, and add a IR emitting code instead."
+#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just a "
+#~ "copy of cbindgen verbatim, and I plan to remove all C and C++ emitting code "
+#~ "from it, and add a IR emitting code instead."
#~ msgstr ""
#~ msgid ""
#~ "When starting working on x-bindgen, I realized I didn't know what to look "
#~ "for in a header file, as I haven't written any C code in many years. So as I"
-#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know "
-#~ "how to build a good C API to expose. So I tried porting the code to C, and "
-#~ "right now I'm working on building a *good* C API for a JSON parser using "
-#~ "parser combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
+#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know how "
+#~ "to build a good C API to expose. So I tried porting the code to C, and right"
+#~ " now I'm working on building a *good* C API for a JSON parser using parser "
+#~ "combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
#~ msgstr ""
#~ msgid ""
diff --git a/locale/eo/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po b/locale/eo/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
index a7e3382..c85754b 100644
--- a/locale/eo/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
+++ b/locale/eo/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
@@ -269,9 +269,9 @@ msgstr ""
msgid ""
"For my personal use, I've [packaged](https://git.euandreh.xyz/package-"
-"repository/) `remembering` for GNU Guix and Nix. Packaging it to any "
-"other distribution should be trivial, or just downloading the tarball and "
-"running `[sudo] make install`."
+"repository/) `remembering` for GNU Guix and Nix. Packaging it to any other "
+"distribution should be trivial, or just downloading the tarball and running "
+"`[sudo] make install`."
msgstr ""
#~ msgid ""
@@ -288,8 +288,8 @@ msgstr ""
#~ msgid ""
#~ "Today I pushed v0.1.0 of "
-#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to "
-#~ "enhance the interactive usability of menu-like tools, such as "
+#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to enhance the "
+#~ "interactive usability of menu-like tools, such as "
#~ "[dmenu](https://tools.suckless.org/dmenu/) and "
#~ "[fzf](https://github.com/junegunn/fzf)."
#~ msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po b/locale/eo/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
index 442e6d0..e30c889 100644
--- a/locale/eo/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
+++ b/locale/eo/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
@@ -241,25 +241,6 @@ msgid ""
msgstr ""
msgid ""
-"--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
-"+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
-"@@ -1,11 +1,11 @@\n"
-" bool a_function() {\n"
-"- char *s1 = malloc(A_NUMBER);\n"
-"+ char *s1 = MALLOC(A_NUMBER);\n"
-" if (!s1) {\n"
-" return false;\n"
-" }\n"
-" strcpy(s1, \"some string\");\n"
-"\n"
-"- char *s2 = malloc(A_NUMBER);\n"
-"+ char *s2 = MALLOC(A_NUMBER);\n"
-" if (!s2) {\n"
-" free(s1);\n"
-" return false;\n"
-msgstr ""
-
-msgid ""
"With this change, if the program gets compiled with the `-DFALLIBLE` flag "
"the fault-injection mechanism will run, and `MALLOC` will fail once for each"
" `filename`+`lineno` combination. When the flag is missing, `MALLOC` is a "
@@ -342,3 +323,41 @@ msgstr ""
msgid "Patches welcome!"
msgstr ""
+
+msgid ""
+"--- 3.c 2021-02-17 00:15:38.019706074 -0300\n"
+"+++ 4.c 2021-02-17 00:44:32.306885590 -0300\n"
+"@@ -1,11 +1,11 @@\n"
+" bool a_function() {\n"
+"- char *s1 = malloc(A_NUMBER);\n"
+"+ char *s1 = MALLOC(A_NUMBER);\n"
+" if (!s1) {\n"
+" return false;\n"
+" }\n"
+" strcpy(s1, \"some string\");\n"
+"\n"
+"- char *s2 = malloc(A_NUMBER);\n"
+"+ char *s2 = MALLOC(A_NUMBER);\n"
+" if (!s2) {\n"
+" free(s1);\n"
+" return false;\n"
+msgstr ""
+
+#~ msgid ""
+#~ "--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
+#~ "+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
+#~ "@@ -1,11 +1,11 @@\n"
+#~ " bool a_function() {\n"
+#~ "- char *s1 = malloc(A_NUMBER);\n"
+#~ "+ char *s1 = MALLOC(A_NUMBER);\n"
+#~ " if (!s1) {\n"
+#~ " return false;\n"
+#~ " }\n"
+#~ " strcpy(s1, \"some string\");\n"
+#~ "\n"
+#~ "- char *s2 = malloc(A_NUMBER);\n"
+#~ "+ char *s2 = MALLOC(A_NUMBER);\n"
+#~ " if (!s2) {\n"
+#~ " free(s1);\n"
+#~ " return false;\n"
+#~ msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po b/locale/eo/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
new file mode 100644
index 0000000..f6e087b
--- /dev/null
+++ b/locale/eo/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
@@ -0,0 +1,70 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: JavaScript naive slugify"
+msgstr ""
+
+msgid "date: 2021-04-03"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: javascript-naive-slugify"
+msgstr ""
+
+msgid ""
+"const s = \"Pézão: açaí, saci-pererê.\";\n"
+"\n"
+"function slugify(s) {\n"
+" return s\n"
+" .toLowerCase()\n"
+" .replaceAll(\":\", \"\")\n"
+" .replaceAll(\".\", \"\")\n"
+" .replaceAll(\",\", \"\")\n"
+" .replaceAll(\"-\", \"\")\n"
+" .replaceAll(\"á\", \"a\")\n"
+" .replaceAll(\"ã\", \"a\")\n"
+" .replaceAll(\"à\", \"a\")\n"
+" .replaceAll(\"é\", \"e\")\n"
+" .replaceAll(\"ê\", \"e\")\n"
+" .replaceAll(\"í\", \"i\")\n"
+" .replaceAll(\"ó\", \"o\")\n"
+" .replaceAll(\"ô\", \"o\")\n"
+" .replaceAll(\"ú\", \"u\")\n"
+" .replaceAll(\"ü\", \"u\")\n"
+" .replaceAll(\"ç\", \"c\");\n"
+"}\n"
+"\n"
+"console.log(slugify(s));\n"
+msgstr ""
+
+#~ msgid ""
+#~ "const s = \"Pézão: açaí, saci-pererê.\";\n"
+#~ "\n"
+#~ "function slugify(s) {\n"
+#~ " return s\n"
+#~ " .toLowerCase()\n"
+#~ " .replaceAll(\":\", \"\")\n"
+#~ " .replaceAll(\".\", \"\")\n"
+#~ " .replaceAll(\",\", \"\")\n"
+#~ " .replaceAll(\"-\", \"\")\n"
+#~ " .replaceAll(\"á\", \"a\")\n"
+#~ " .replaceAll(\"ã\", \"a\")\n"
+#~ " .replaceAll(\"à\", \"a\")\n"
+#~ " .replaceAll(\"é\", \"e\")\n"
+#~ " .replaceAll(\"ê\", \"e\")\n"
+#~ " .replaceAll(\"í\", \"i\")\n"
+#~ " .replaceAll(\"ó\", \"o\")\n"
+#~ " .replaceAll(\"ô\", \"o\")\n"
+#~ " .replaceAll(\"ú\", \"u\")\n"
+#~ " .replaceAll(\"ü\", \"u\")\n"
+#~ " .replaceAll(\"ç\", \"c\");\n"
+#~ "}\n"
+#~ "\n"
+#~ "console.log(slugify(s));\n"
+#~ msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po b/locale/eo/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
index badc41e..d0e9b44 100644
--- a/locale/eo/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
+++ b/locale/eo/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
@@ -57,14 +57,6 @@ msgid "It assumes that `$HOME/.local/bin` is in `$PATH`."
msgstr ""
msgid ""
-"This screencast is a simple demo of automating the installation of Alpine "
-"Linux 3.12.3 standard x86_64 with "
-"[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more "
-"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
-"Makefiles glued together."
-msgstr ""
-
-msgid ""
"pushd `mktemp -d`\n"
"git clone https://git.euandreh.xyz/autoqemu .\n"
"make\n"
@@ -72,6 +64,22 @@ msgid ""
"autoqemu ssh alpine\n"
msgstr ""
+msgid ""
+"This screencast is a simple demo of automating the installation of Alpine "
+"Linux 3.12.3 standard x86_64 with "
+"[AutoQEMU](https://git.euandreh.xyz/autoqemu/about), which is nothing more "
+"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+"Makefiles glued together."
+msgstr ""
+
+#~ msgid ""
+#~ "This screencast is a simple demo of automating the installation of Alpine "
+#~ "Linux 3.12.3 standard x86_64 with "
+#~ "[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more than "
+#~ "POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+#~ "Makefiles glued together."
+#~ msgstr ""
+
#~ msgid ""
#~ "pushd `mktemp -d`\n"
#~ "git clone https://git.euandreh.xyz/autoqemu .\n"
diff --git a/locale/eo/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po b/locale/eo/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
index 421e295..6030e0c 100644
--- a/locale/eo/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
+++ b/locale/eo/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
@@ -49,9 +49,6 @@ msgid ""
"current staging area back to what it was before the checkout."
msgstr ""
-msgid "References:"
-msgstr ""
-
msgid ""
"[GIT: Checkout to a specific folder](https://stackoverflow.com/a/16493707) "
"(StackOverflow)"
@@ -107,6 +104,12 @@ msgstr ""
msgid "eu_categories: git"
msgstr ""
+msgid "References"
+msgstr ""
+
+#~ msgid "References:"
+#~ msgstr ""
+
#~ msgid ""
#~ "title: Browse a git repository at a specific commit\n"
#~ "date: 2020-08-14\n"
diff --git a/locale/eo/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po b/locale/eo/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
index 182061b..1610cea 100644
--- a/locale/eo/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
+++ b/locale/eo/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
@@ -25,9 +25,9 @@ msgid ""
"The only difference is that you're working with only Git itself, so you're "
"not tied to any Git hosting provider: you can send pull requests across them"
" transparently! You could even use your own "
-"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked"
-" in by any of them, putting the \"D\" back in \"DVCS\": it's a "
-"**distributed** version control system."
+"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked in by"
+" any of them, putting the \"D\" back in \"DVCS\": it's a **distributed** "
+"version control system."
msgstr ""
msgid "`git request-pull` introduction"
diff --git a/locale/eo/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po b/locale/eo/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
new file mode 100644
index 0000000..ab59a4f
--- /dev/null
+++ b/locale/eo/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
@@ -0,0 +1,220 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Clojure auto curry"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: clojure-auto-curry"
+msgstr ""
+
+msgid "A naive `add` definition, alongside its usage and macroexpansion:"
+msgstr ""
+
+msgid ""
+"user=> (defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))\n"
+"#'user/add\n"
+"\n"
+"user=> (add 1)\n"
+"#object[clojure.core$partial$fn__5857 0x2c708440 \"clojure.core$partial$fn__5857@2c708440\"]\n"
+"\n"
+"user=> (add 1 2 3 4)\n"
+"#object[clojure.core$partial$fn__5863 0xf4c0e4e \"clojure.core$partial$fn__5863@f4c0e4e\"]\n"
+"\n"
+"user=> ((add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"user=> (((add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"user=> (use 'clojure.pprint)\n"
+"nil\n"
+"\n"
+"user=> (pprint\n"
+" (macroexpand\n"
+" '(defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))))\n"
+"(def\n"
+" add\n"
+" (clojure.core/fn\n"
+" ([a b c d e] (+ 1 2 3 4 5))\n"
+" ([a] (clojure.core/partial add a))\n"
+" ([a b] (clojure.core/partial add a b))\n"
+" ([a b c] (clojure.core/partial add a b c))\n"
+" ([a b c d] (clojure.core/partial add a b c d))))\n"
+"nil\n"
+msgstr ""
+
+msgid ""
+"This simplistic `defcurry` definition doesn't support optional parameters, "
+"multi-arity, `&` rest arguments, docstrings, etc., but it could certainly "
+"evolve to do so."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Same Clojure as before, now with auto-currying via macros."
+msgstr ""
+
+msgid ""
+"Here's a simple macro defined by [Loretta "
+"He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+"create Clojure functions that are curried on all arguments, relying on "
+"Clojure's multi-arity support:"
+msgstr ""
+
+msgid "date: 2021-04-24 1"
+msgstr ""
+
+msgid ""
+"(defmacro defcurry\n"
+" [name args & body]\n"
+" (let [partials (map (fn [n]\n"
+" `(~(subvec args 0 n) (partial ~name ~@(take n args))))\n"
+" (range 1 (count args)))]\n"
+" `(defn ~name\n"
+" (~args ~@body)\n"
+" ~@partials)))\n"
+msgstr ""
+
+msgid "Comparison with Common Lisp"
+msgstr ""
+
+msgid "My attempt at writing an equivalent for Common Lisp gives me:"
+msgstr ""
+
+msgid ""
+"(defun partial (fn &rest args)\n"
+" (lambda (&rest args2)\n"
+" (apply fn (append args args2))))\n"
+"\n"
+"(defun curry-n (n func)\n"
+" (cond ((< n 0) (error \"Too many arguments\"))\n"
+" ((zerop n) (funcall func))\n"
+" (t (lambda (&rest rest)\n"
+" (curry-n (- n (length rest))\n"
+" (apply #'partial func rest))))))\n"
+"\n"
+"(defmacro defcurry (name args &body body)\n"
+" `(defun ,name (&rest rest)\n"
+" (let ((func (lambda ,args ,@body)))\n"
+" (curry-n (- ,(length args) (length rest))\n"
+" (apply #'partial func rest)))))\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "The usage is pretty similar:"
+msgstr ""
+
+msgid ""
+"* (defcurry add (a b c d e)\n"
+" (+ a b c d e))\n"
+"ADD\n"
+"\n"
+"* (add 1)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216419B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216537B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"* (funcall (funcall (add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"* (macroexpand-1\n"
+" '(defcurry add (a b c d e)\n"
+" (+ a b c d e)))\n"
+"(DEFUN ADD (&REST REST)\n"
+" (LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E))))\n"
+" (CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST))))\n"
+"T\n"
+msgstr ""
+
+msgid ""
+"This also require `funcall`s, since we return a `lambda` that doesn't live "
+"in the function namespace."
+msgstr ""
+
+msgid ""
+"Like the Clojure one, it doesn't support optional parameters, `&rest` rest "
+"arguments, docstrings, etc., but it also could evolve to do so."
+msgstr ""
+
+msgid "updated_at: 2021-04-27"
+msgstr ""
+
+#~ msgid ""
+#~ "(defmacro defcurry\n"
+#~ " [fname args & body]\n"
+#~ " (let [partials (map (fn [n]\n"
+#~ " `(~(subvec args 0 n) (partial ~fname ~@(take n args))))\n"
+#~ " (range 1 (count args)))]\n"
+#~ " `(defn ~fname\n"
+#~ " (~args ~@body)\n"
+#~ " ~@partials)))\n"
+#~ msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "A simple macro defined by [Loretta "
+#~ "He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+#~ "create Clojure functions that are curried on all arguments, relying on "
+#~ "Clojure's multi-arity support:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Without built-in multi-arity support, we have to do more work, like tracking"
+#~ " the number of arguments consumed so far. That is, without dependending on "
+#~ "any library, sticking to ANSI Common Lisp."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po b/locale/eo/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
new file mode 100644
index 0000000..6aa66a8
--- /dev/null
+++ b/locale/eo/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
@@ -0,0 +1,210 @@
+#
+msgid ""
+msgstr ""
+
+msgid ""
+"title: Common Lisp argument precedence order parameterization of a generic "
+"function"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid ""
+"ref: common-lisp-argument-precedence-order-parameterization-of-a-generic-"
+"function"
+msgstr ""
+
+msgid ""
+"When CLOS dispatches a method, it picks the most specific method definition "
+"to the argument list:"
+msgstr ""
+
+msgid ""
+"\n"
+"* (defgeneric a-fn (x))\n"
+"#<STANDARD-GENERIC-FUNCTION A-FN (0) {5815ACB9}>\n"
+"\n"
+"* (defmethod a-fn (x) :default-method)\n"
+"#<STANDARD-METHOD A-FN (T) {581DB535}>\n"
+"\n"
+"* (defmethod a-fn ((x number)) :a-number)\n"
+"#<STANDARD-METHOD A-FN (NUMBER) {58241645}>\n"
+"\n"
+"* (defmethod a-fn ((x (eql 1))) :number-1)\n"
+"#<STANDARD-METHOD A-FN ((EQL 1)) {582A7D75}>\n"
+"\n"
+"* (a-fn nil)\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn \"1\")\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn 0)\n"
+":A-NUMBER\n"
+"\n"
+"* (a-fn 1)\n"
+":NUMBER-1\n"
+msgstr ""
+
+msgid ""
+"CLOS uses a similar logic when choosing the method from parent classes, when"
+" multiple ones are available:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-A {583E0B25}>\n"
+"* (defclass class-b () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-B {583E7F6D}>\n"
+"* (defgeneric another-fn (obj))\n"
+"\n"
+"#<STANDARD-GENERIC-FUNCTION ANOTHER-FN (0) {583DA749}>\n"
+"* (defmethod another-fn ((obj class-a)) :class-a)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-A) {584523C5}>\n"
+"* (defmethod another-fn ((obj class-b)) :class-b)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-B) {584B8895}>\n"
+msgstr ""
+
+msgid ""
+"Given the above definitions, when inheriting from `class-a` and `class-b`, "
+"the order of inheritance matters:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a-coming-first (class-a class-b) ())\n"
+"#<STANDARD-CLASS CLASS-A-COMING-FIRST {584BE6AD}>\n"
+"\n"
+"* (defclass class-b-coming-first (class-b class-a) ())\n"
+"#<STANDARD-CLASS CLASS-B-COMING-FIRST {584C744D}>\n"
+"\n"
+"* (another-fn (make-instance 'class-a-coming-first))\n"
+":CLASS-A\n"
+"\n"
+"* (another-fn (make-instance 'class-b-coming-first))\n"
+":CLASS-B\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (0) {584D9EC9}>\n"
+"\n"
+"* (defmethod yet-another-fn ((obj1 class-a) obj2) :first-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (CLASS-A T) {5854269D}>\n"
+"\n"
+"* (defmethod yet-another-fn (obj1 (obj2 class-b)) :second-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (T CLASS-B) {585AAAAD}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":FIRST-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"For that, we use the `:argument-precedence-order` option when declaring a "
+"generic function:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2) (:argument-precedence-order obj2 obj1))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (2) {584D9EC9}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":SECOND-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Comparison with Clojure"
+msgstr ""
+
+msgid "Clojure has an equivalent, when using `defmulti`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Conclusion"
+msgstr ""
+
+msgid ""
+"Making the argument precedence order configurable for generic functions but "
+"not for class definitions makes a lot of sense."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "TIL."
+msgstr ""
+
+msgid ""
+"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?"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid ""
+"[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"
+msgstr ""
+
+msgid "date: 2021-04-24 2"
+msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 to the"
+#~ " choice to be based on the second argument first?"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "When declaring a class, we can choose the precedence order, and that is "
+#~ "about it. But when defining a generic function, the order of argumentws is "
+#~ "more important to the function semantics, and the argument precedence being "
+#~ "left-to-right is just the default behaviour."
+#~ msgstr ""
diff --git a/locale/eo/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po b/locale/eo/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
new file mode 100644
index 0000000..925a00b
--- /dev/null
+++ b/locale/eo/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
@@ -0,0 +1,95 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Three-way conditional for number signs"
+msgstr ""
+
+msgid "date: 2021-04-24 3"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: three-way-conditional-for-number-signs"
+msgstr ""
+
+msgid ""
+"A useful macro from Paul Graham's [On "
+"Lisp](http://www.paulgraham.com/onlisptext.html) book:"
+msgstr ""
+
+msgid ""
+"(defmacro nif (expr pos zero neg)\n"
+" (let ((g (gensym)))\n"
+" `(let ((,g ,expr))\n"
+" (cond ((plusp ,g) ,pos)\n"
+" ((zerop ,g) ,zero)\n"
+" (t ,neg)))))\n"
+msgstr ""
+
+msgid ""
+"The latest example I can think of is section 1.3.3 of [Structure and "
+"Interpretation of Computer "
+"Programs](https://mitpress.mit.edu/sites/default/files/sicp/index.html), "
+"which I was reading recently:"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (let ((test-value (f midpoint)))\n"
+" (cond ((positive? test-value)\n"
+" (search f neg-point midpoint))\n"
+" ((negative? test-value)\n"
+" (search f midpoint pos-point))\n"
+" (else midpoint))))))\n"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (nif (f midpoint)\n"
+" (search f neg-point midpoint)\n"
+" (midpoint)\n"
+" (search f midpoint pos-point)))))\n"
+msgstr ""
+
+msgid ""
+"It also avoids `cond`'s extra clunky parentheses for grouping, which is "
+"unnecessary but built-in."
+msgstr ""
+
+msgid ""
+"As a macro, I personally feel it tilts the balance towards expressivenes "
+"despite its extra cognitive load toll."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+#~ msgid ""
+#~ "After I looked at this macro, I started seeing opportunities to using it in "
+#~ "many places, and yet I didn't see anyonelse using it."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Not that the book should introduce such macro this early, but I couldn't "
+#~ "avoid feeling bothered by not using a `nif` macro, which could even remove "
+#~ "the need for the intermediate `test-value` variable:"
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po b/locale/fr/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
index 86c8389..3c7e6ec 100644
--- a/locale/fr/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
+++ b/locale/fr/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
@@ -12,8 +12,8 @@ msgstr ""
msgid ""
"I wrote a simple little tool called "
-"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick"
-" Swift's package manager into assuming everything is set up. Here's the "
+"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick "
+"Swift's package manager into assuming everything is set up. Here's the "
"example from swift2nix's README file:"
msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po b/locale/fr/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
index 0e0bc8c..ecd28a5 100644
--- a/locale/fr/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
+++ b/locale/fr/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
@@ -381,18 +381,18 @@ msgstr ""
#~ msgid ""
#~ "I've started a fork of cbindgen: "
-#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just "
-#~ "a copy of cbindgen verbatim, and I plan to remove all C and C++ emitting "
-#~ "code from it, and add a IR emitting code instead."
+#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just a "
+#~ "copy of cbindgen verbatim, and I plan to remove all C and C++ emitting code "
+#~ "from it, and add a IR emitting code instead."
#~ msgstr ""
#~ msgid ""
#~ "When starting working on x-bindgen, I realized I didn't know what to look "
#~ "for in a header file, as I haven't written any C code in many years. So as I"
-#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know "
-#~ "how to build a good C API to expose. So I tried porting the code to C, and "
-#~ "right now I'm working on building a *good* C API for a JSON parser using "
-#~ "parser combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
+#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know how "
+#~ "to build a good C API to expose. So I tried porting the code to C, and right"
+#~ " now I'm working on building a *good* C API for a JSON parser using parser "
+#~ "combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
#~ msgstr ""
#~ msgid ""
diff --git a/locale/fr/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po b/locale/fr/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
index a7e3382..c85754b 100644
--- a/locale/fr/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
+++ b/locale/fr/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
@@ -269,9 +269,9 @@ msgstr ""
msgid ""
"For my personal use, I've [packaged](https://git.euandreh.xyz/package-"
-"repository/) `remembering` for GNU Guix and Nix. Packaging it to any "
-"other distribution should be trivial, or just downloading the tarball and "
-"running `[sudo] make install`."
+"repository/) `remembering` for GNU Guix and Nix. Packaging it to any other "
+"distribution should be trivial, or just downloading the tarball and running "
+"`[sudo] make install`."
msgstr ""
#~ msgid ""
@@ -288,8 +288,8 @@ msgstr ""
#~ msgid ""
#~ "Today I pushed v0.1.0 of "
-#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to "
-#~ "enhance the interactive usability of menu-like tools, such as "
+#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to enhance the "
+#~ "interactive usability of menu-like tools, such as "
#~ "[dmenu](https://tools.suckless.org/dmenu/) and "
#~ "[fzf](https://github.com/junegunn/fzf)."
#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po b/locale/fr/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
index 442e6d0..e30c889 100644
--- a/locale/fr/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
+++ b/locale/fr/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
@@ -241,25 +241,6 @@ msgid ""
msgstr ""
msgid ""
-"--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
-"+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
-"@@ -1,11 +1,11 @@\n"
-" bool a_function() {\n"
-"- char *s1 = malloc(A_NUMBER);\n"
-"+ char *s1 = MALLOC(A_NUMBER);\n"
-" if (!s1) {\n"
-" return false;\n"
-" }\n"
-" strcpy(s1, \"some string\");\n"
-"\n"
-"- char *s2 = malloc(A_NUMBER);\n"
-"+ char *s2 = MALLOC(A_NUMBER);\n"
-" if (!s2) {\n"
-" free(s1);\n"
-" return false;\n"
-msgstr ""
-
-msgid ""
"With this change, if the program gets compiled with the `-DFALLIBLE` flag "
"the fault-injection mechanism will run, and `MALLOC` will fail once for each"
" `filename`+`lineno` combination. When the flag is missing, `MALLOC` is a "
@@ -342,3 +323,41 @@ msgstr ""
msgid "Patches welcome!"
msgstr ""
+
+msgid ""
+"--- 3.c 2021-02-17 00:15:38.019706074 -0300\n"
+"+++ 4.c 2021-02-17 00:44:32.306885590 -0300\n"
+"@@ -1,11 +1,11 @@\n"
+" bool a_function() {\n"
+"- char *s1 = malloc(A_NUMBER);\n"
+"+ char *s1 = MALLOC(A_NUMBER);\n"
+" if (!s1) {\n"
+" return false;\n"
+" }\n"
+" strcpy(s1, \"some string\");\n"
+"\n"
+"- char *s2 = malloc(A_NUMBER);\n"
+"+ char *s2 = MALLOC(A_NUMBER);\n"
+" if (!s2) {\n"
+" free(s1);\n"
+" return false;\n"
+msgstr ""
+
+#~ msgid ""
+#~ "--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
+#~ "+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
+#~ "@@ -1,11 +1,11 @@\n"
+#~ " bool a_function() {\n"
+#~ "- char *s1 = malloc(A_NUMBER);\n"
+#~ "+ char *s1 = MALLOC(A_NUMBER);\n"
+#~ " if (!s1) {\n"
+#~ " return false;\n"
+#~ " }\n"
+#~ " strcpy(s1, \"some string\");\n"
+#~ "\n"
+#~ "- char *s2 = malloc(A_NUMBER);\n"
+#~ "+ char *s2 = MALLOC(A_NUMBER);\n"
+#~ " if (!s2) {\n"
+#~ " free(s1);\n"
+#~ " return false;\n"
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po b/locale/fr/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
new file mode 100644
index 0000000..f6e087b
--- /dev/null
+++ b/locale/fr/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
@@ -0,0 +1,70 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: JavaScript naive slugify"
+msgstr ""
+
+msgid "date: 2021-04-03"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: javascript-naive-slugify"
+msgstr ""
+
+msgid ""
+"const s = \"Pézão: açaí, saci-pererê.\";\n"
+"\n"
+"function slugify(s) {\n"
+" return s\n"
+" .toLowerCase()\n"
+" .replaceAll(\":\", \"\")\n"
+" .replaceAll(\".\", \"\")\n"
+" .replaceAll(\",\", \"\")\n"
+" .replaceAll(\"-\", \"\")\n"
+" .replaceAll(\"á\", \"a\")\n"
+" .replaceAll(\"ã\", \"a\")\n"
+" .replaceAll(\"à\", \"a\")\n"
+" .replaceAll(\"é\", \"e\")\n"
+" .replaceAll(\"ê\", \"e\")\n"
+" .replaceAll(\"í\", \"i\")\n"
+" .replaceAll(\"ó\", \"o\")\n"
+" .replaceAll(\"ô\", \"o\")\n"
+" .replaceAll(\"ú\", \"u\")\n"
+" .replaceAll(\"ü\", \"u\")\n"
+" .replaceAll(\"ç\", \"c\");\n"
+"}\n"
+"\n"
+"console.log(slugify(s));\n"
+msgstr ""
+
+#~ msgid ""
+#~ "const s = \"Pézão: açaí, saci-pererê.\";\n"
+#~ "\n"
+#~ "function slugify(s) {\n"
+#~ " return s\n"
+#~ " .toLowerCase()\n"
+#~ " .replaceAll(\":\", \"\")\n"
+#~ " .replaceAll(\".\", \"\")\n"
+#~ " .replaceAll(\",\", \"\")\n"
+#~ " .replaceAll(\"-\", \"\")\n"
+#~ " .replaceAll(\"á\", \"a\")\n"
+#~ " .replaceAll(\"ã\", \"a\")\n"
+#~ " .replaceAll(\"à\", \"a\")\n"
+#~ " .replaceAll(\"é\", \"e\")\n"
+#~ " .replaceAll(\"ê\", \"e\")\n"
+#~ " .replaceAll(\"í\", \"i\")\n"
+#~ " .replaceAll(\"ó\", \"o\")\n"
+#~ " .replaceAll(\"ô\", \"o\")\n"
+#~ " .replaceAll(\"ú\", \"u\")\n"
+#~ " .replaceAll(\"ü\", \"u\")\n"
+#~ " .replaceAll(\"ç\", \"c\");\n"
+#~ "}\n"
+#~ "\n"
+#~ "console.log(slugify(s));\n"
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po b/locale/fr/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
index badc41e..d0e9b44 100644
--- a/locale/fr/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
+++ b/locale/fr/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
@@ -57,14 +57,6 @@ msgid "It assumes that `$HOME/.local/bin` is in `$PATH`."
msgstr ""
msgid ""
-"This screencast is a simple demo of automating the installation of Alpine "
-"Linux 3.12.3 standard x86_64 with "
-"[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more "
-"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
-"Makefiles glued together."
-msgstr ""
-
-msgid ""
"pushd `mktemp -d`\n"
"git clone https://git.euandreh.xyz/autoqemu .\n"
"make\n"
@@ -72,6 +64,22 @@ msgid ""
"autoqemu ssh alpine\n"
msgstr ""
+msgid ""
+"This screencast is a simple demo of automating the installation of Alpine "
+"Linux 3.12.3 standard x86_64 with "
+"[AutoQEMU](https://git.euandreh.xyz/autoqemu/about), which is nothing more "
+"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+"Makefiles glued together."
+msgstr ""
+
+#~ msgid ""
+#~ "This screencast is a simple demo of automating the installation of Alpine "
+#~ "Linux 3.12.3 standard x86_64 with "
+#~ "[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more than "
+#~ "POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+#~ "Makefiles glued together."
+#~ msgstr ""
+
#~ msgid ""
#~ "pushd `mktemp -d`\n"
#~ "git clone https://git.euandreh.xyz/autoqemu .\n"
diff --git a/locale/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po b/locale/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
index 421e295..6030e0c 100644
--- a/locale/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
+++ b/locale/fr/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
@@ -49,9 +49,6 @@ msgid ""
"current staging area back to what it was before the checkout."
msgstr ""
-msgid "References:"
-msgstr ""
-
msgid ""
"[GIT: Checkout to a specific folder](https://stackoverflow.com/a/16493707) "
"(StackOverflow)"
@@ -107,6 +104,12 @@ msgstr ""
msgid "eu_categories: git"
msgstr ""
+msgid "References"
+msgstr ""
+
+#~ msgid "References:"
+#~ msgstr ""
+
#~ msgid ""
#~ "title: Browse a git repository at a specific commit\n"
#~ "date: 2020-08-14\n"
diff --git a/locale/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po b/locale/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
index 182061b..1610cea 100644
--- a/locale/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
+++ b/locale/fr/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
@@ -25,9 +25,9 @@ msgid ""
"The only difference is that you're working with only Git itself, so you're "
"not tied to any Git hosting provider: you can send pull requests across them"
" transparently! You could even use your own "
-"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked"
-" in by any of them, putting the \"D\" back in \"DVCS\": it's a "
-"**distributed** version control system."
+"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked in by"
+" any of them, putting the \"D\" back in \"DVCS\": it's a **distributed** "
+"version control system."
msgstr ""
msgid "`git request-pull` introduction"
diff --git a/locale/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po b/locale/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
new file mode 100644
index 0000000..ab59a4f
--- /dev/null
+++ b/locale/fr/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
@@ -0,0 +1,220 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Clojure auto curry"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: clojure-auto-curry"
+msgstr ""
+
+msgid "A naive `add` definition, alongside its usage and macroexpansion:"
+msgstr ""
+
+msgid ""
+"user=> (defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))\n"
+"#'user/add\n"
+"\n"
+"user=> (add 1)\n"
+"#object[clojure.core$partial$fn__5857 0x2c708440 \"clojure.core$partial$fn__5857@2c708440\"]\n"
+"\n"
+"user=> (add 1 2 3 4)\n"
+"#object[clojure.core$partial$fn__5863 0xf4c0e4e \"clojure.core$partial$fn__5863@f4c0e4e\"]\n"
+"\n"
+"user=> ((add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"user=> (((add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"user=> (use 'clojure.pprint)\n"
+"nil\n"
+"\n"
+"user=> (pprint\n"
+" (macroexpand\n"
+" '(defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))))\n"
+"(def\n"
+" add\n"
+" (clojure.core/fn\n"
+" ([a b c d e] (+ 1 2 3 4 5))\n"
+" ([a] (clojure.core/partial add a))\n"
+" ([a b] (clojure.core/partial add a b))\n"
+" ([a b c] (clojure.core/partial add a b c))\n"
+" ([a b c d] (clojure.core/partial add a b c d))))\n"
+"nil\n"
+msgstr ""
+
+msgid ""
+"This simplistic `defcurry` definition doesn't support optional parameters, "
+"multi-arity, `&` rest arguments, docstrings, etc., but it could certainly "
+"evolve to do so."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Same Clojure as before, now with auto-currying via macros."
+msgstr ""
+
+msgid ""
+"Here's a simple macro defined by [Loretta "
+"He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+"create Clojure functions that are curried on all arguments, relying on "
+"Clojure's multi-arity support:"
+msgstr ""
+
+msgid "date: 2021-04-24 1"
+msgstr ""
+
+msgid ""
+"(defmacro defcurry\n"
+" [name args & body]\n"
+" (let [partials (map (fn [n]\n"
+" `(~(subvec args 0 n) (partial ~name ~@(take n args))))\n"
+" (range 1 (count args)))]\n"
+" `(defn ~name\n"
+" (~args ~@body)\n"
+" ~@partials)))\n"
+msgstr ""
+
+msgid "Comparison with Common Lisp"
+msgstr ""
+
+msgid "My attempt at writing an equivalent for Common Lisp gives me:"
+msgstr ""
+
+msgid ""
+"(defun partial (fn &rest args)\n"
+" (lambda (&rest args2)\n"
+" (apply fn (append args args2))))\n"
+"\n"
+"(defun curry-n (n func)\n"
+" (cond ((< n 0) (error \"Too many arguments\"))\n"
+" ((zerop n) (funcall func))\n"
+" (t (lambda (&rest rest)\n"
+" (curry-n (- n (length rest))\n"
+" (apply #'partial func rest))))))\n"
+"\n"
+"(defmacro defcurry (name args &body body)\n"
+" `(defun ,name (&rest rest)\n"
+" (let ((func (lambda ,args ,@body)))\n"
+" (curry-n (- ,(length args) (length rest))\n"
+" (apply #'partial func rest)))))\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "The usage is pretty similar:"
+msgstr ""
+
+msgid ""
+"* (defcurry add (a b c d e)\n"
+" (+ a b c d e))\n"
+"ADD\n"
+"\n"
+"* (add 1)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216419B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216537B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"* (funcall (funcall (add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"* (macroexpand-1\n"
+" '(defcurry add (a b c d e)\n"
+" (+ a b c d e)))\n"
+"(DEFUN ADD (&REST REST)\n"
+" (LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E))))\n"
+" (CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST))))\n"
+"T\n"
+msgstr ""
+
+msgid ""
+"This also require `funcall`s, since we return a `lambda` that doesn't live "
+"in the function namespace."
+msgstr ""
+
+msgid ""
+"Like the Clojure one, it doesn't support optional parameters, `&rest` rest "
+"arguments, docstrings, etc., but it also could evolve to do so."
+msgstr ""
+
+msgid "updated_at: 2021-04-27"
+msgstr ""
+
+#~ msgid ""
+#~ "(defmacro defcurry\n"
+#~ " [fname args & body]\n"
+#~ " (let [partials (map (fn [n]\n"
+#~ " `(~(subvec args 0 n) (partial ~fname ~@(take n args))))\n"
+#~ " (range 1 (count args)))]\n"
+#~ " `(defn ~fname\n"
+#~ " (~args ~@body)\n"
+#~ " ~@partials)))\n"
+#~ msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "A simple macro defined by [Loretta "
+#~ "He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+#~ "create Clojure functions that are curried on all arguments, relying on "
+#~ "Clojure's multi-arity support:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Without built-in multi-arity support, we have to do more work, like tracking"
+#~ " the number of arguments consumed so far. That is, without dependending on "
+#~ "any library, sticking to ANSI Common Lisp."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po b/locale/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
new file mode 100644
index 0000000..6aa66a8
--- /dev/null
+++ b/locale/fr/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
@@ -0,0 +1,210 @@
+#
+msgid ""
+msgstr ""
+
+msgid ""
+"title: Common Lisp argument precedence order parameterization of a generic "
+"function"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid ""
+"ref: common-lisp-argument-precedence-order-parameterization-of-a-generic-"
+"function"
+msgstr ""
+
+msgid ""
+"When CLOS dispatches a method, it picks the most specific method definition "
+"to the argument list:"
+msgstr ""
+
+msgid ""
+"\n"
+"* (defgeneric a-fn (x))\n"
+"#<STANDARD-GENERIC-FUNCTION A-FN (0) {5815ACB9}>\n"
+"\n"
+"* (defmethod a-fn (x) :default-method)\n"
+"#<STANDARD-METHOD A-FN (T) {581DB535}>\n"
+"\n"
+"* (defmethod a-fn ((x number)) :a-number)\n"
+"#<STANDARD-METHOD A-FN (NUMBER) {58241645}>\n"
+"\n"
+"* (defmethod a-fn ((x (eql 1))) :number-1)\n"
+"#<STANDARD-METHOD A-FN ((EQL 1)) {582A7D75}>\n"
+"\n"
+"* (a-fn nil)\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn \"1\")\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn 0)\n"
+":A-NUMBER\n"
+"\n"
+"* (a-fn 1)\n"
+":NUMBER-1\n"
+msgstr ""
+
+msgid ""
+"CLOS uses a similar logic when choosing the method from parent classes, when"
+" multiple ones are available:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-A {583E0B25}>\n"
+"* (defclass class-b () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-B {583E7F6D}>\n"
+"* (defgeneric another-fn (obj))\n"
+"\n"
+"#<STANDARD-GENERIC-FUNCTION ANOTHER-FN (0) {583DA749}>\n"
+"* (defmethod another-fn ((obj class-a)) :class-a)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-A) {584523C5}>\n"
+"* (defmethod another-fn ((obj class-b)) :class-b)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-B) {584B8895}>\n"
+msgstr ""
+
+msgid ""
+"Given the above definitions, when inheriting from `class-a` and `class-b`, "
+"the order of inheritance matters:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a-coming-first (class-a class-b) ())\n"
+"#<STANDARD-CLASS CLASS-A-COMING-FIRST {584BE6AD}>\n"
+"\n"
+"* (defclass class-b-coming-first (class-b class-a) ())\n"
+"#<STANDARD-CLASS CLASS-B-COMING-FIRST {584C744D}>\n"
+"\n"
+"* (another-fn (make-instance 'class-a-coming-first))\n"
+":CLASS-A\n"
+"\n"
+"* (another-fn (make-instance 'class-b-coming-first))\n"
+":CLASS-B\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (0) {584D9EC9}>\n"
+"\n"
+"* (defmethod yet-another-fn ((obj1 class-a) obj2) :first-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (CLASS-A T) {5854269D}>\n"
+"\n"
+"* (defmethod yet-another-fn (obj1 (obj2 class-b)) :second-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (T CLASS-B) {585AAAAD}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":FIRST-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"For that, we use the `:argument-precedence-order` option when declaring a "
+"generic function:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2) (:argument-precedence-order obj2 obj1))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (2) {584D9EC9}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":SECOND-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Comparison with Clojure"
+msgstr ""
+
+msgid "Clojure has an equivalent, when using `defmulti`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Conclusion"
+msgstr ""
+
+msgid ""
+"Making the argument precedence order configurable for generic functions but "
+"not for class definitions makes a lot of sense."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "TIL."
+msgstr ""
+
+msgid ""
+"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?"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid ""
+"[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"
+msgstr ""
+
+msgid "date: 2021-04-24 2"
+msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 to the"
+#~ " choice to be based on the second argument first?"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "When declaring a class, we can choose the precedence order, and that is "
+#~ "about it. But when defining a generic function, the order of argumentws is "
+#~ "more important to the function semantics, and the argument precedence being "
+#~ "left-to-right is just the default behaviour."
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po b/locale/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
new file mode 100644
index 0000000..925a00b
--- /dev/null
+++ b/locale/fr/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
@@ -0,0 +1,95 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Three-way conditional for number signs"
+msgstr ""
+
+msgid "date: 2021-04-24 3"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: three-way-conditional-for-number-signs"
+msgstr ""
+
+msgid ""
+"A useful macro from Paul Graham's [On "
+"Lisp](http://www.paulgraham.com/onlisptext.html) book:"
+msgstr ""
+
+msgid ""
+"(defmacro nif (expr pos zero neg)\n"
+" (let ((g (gensym)))\n"
+" `(let ((,g ,expr))\n"
+" (cond ((plusp ,g) ,pos)\n"
+" ((zerop ,g) ,zero)\n"
+" (t ,neg)))))\n"
+msgstr ""
+
+msgid ""
+"The latest example I can think of is section 1.3.3 of [Structure and "
+"Interpretation of Computer "
+"Programs](https://mitpress.mit.edu/sites/default/files/sicp/index.html), "
+"which I was reading recently:"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (let ((test-value (f midpoint)))\n"
+" (cond ((positive? test-value)\n"
+" (search f neg-point midpoint))\n"
+" ((negative? test-value)\n"
+" (search f midpoint pos-point))\n"
+" (else midpoint))))))\n"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (nif (f midpoint)\n"
+" (search f neg-point midpoint)\n"
+" (midpoint)\n"
+" (search f midpoint pos-point)))))\n"
+msgstr ""
+
+msgid ""
+"It also avoids `cond`'s extra clunky parentheses for grouping, which is "
+"unnecessary but built-in."
+msgstr ""
+
+msgid ""
+"As a macro, I personally feel it tilts the balance towards expressivenes "
+"despite its extra cognitive load toll."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+#~ msgid ""
+#~ "After I looked at this macro, I started seeing opportunities to using it in "
+#~ "many places, and yet I didn't see anyonelse using it."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Not that the book should introduce such macro this early, but I couldn't "
+#~ "avoid feeling bothered by not using a `nif` macro, which could even remove "
+#~ "the need for the intermediate `test-value` variable:"
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po b/locale/pt/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
index 86c8389..3c7e6ec 100644
--- a/locale/pt/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
+++ b/locale/pt/LC_MESSAGES/_articles/2020-10-05-swift2nix-run-swift-inside-nix-builds.po
@@ -12,8 +12,8 @@ msgstr ""
msgid ""
"I wrote a simple little tool called "
-"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick"
-" Swift's package manager into assuming everything is set up. Here's the "
+"[swift2nix](https://git.euandreh.xyz/swift2nix/) that allows you trick "
+"Swift's package manager into assuming everything is set up. Here's the "
"example from swift2nix's README file:"
msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po b/locale/pt/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
index 0e0bc8c..ecd28a5 100644
--- a/locale/pt/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
+++ b/locale/pt/LC_MESSAGES/_articles/2020-11-12-durable-persistent-trees-and-parser-combinators-building-a-database.po
@@ -381,18 +381,18 @@ msgstr ""
#~ msgid ""
#~ "I've started a fork of cbindgen: "
-#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just "
-#~ "a copy of cbindgen verbatim, and I plan to remove all C and C++ emitting "
-#~ "code from it, and add a IR emitting code instead."
+#~ "[x-bindgen](https://git.euandreh.xyz/x-bindgen/). Right now it is just a "
+#~ "copy of cbindgen verbatim, and I plan to remove all C and C++ emitting code "
+#~ "from it, and add a IR emitting code instead."
#~ msgstr ""
#~ msgid ""
#~ "When starting working on x-bindgen, I realized I didn't know what to look "
#~ "for in a header file, as I haven't written any C code in many years. So as I"
-#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know "
-#~ "how to build a good C API to expose. So I tried porting the code to C, and "
-#~ "right now I'm working on building a *good* C API for a JSON parser using "
-#~ "parser combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
+#~ " was writing [libedn](https://git.euandreh.xyz/libedn/), I didn't know how "
+#~ "to build a good C API to expose. So I tried porting the code to C, and right"
+#~ " now I'm working on building a *good* C API for a JSON parser using parser "
+#~ "combinators: [ParsecC](https://git.euandreh.xyz/parsecc/)."
#~ msgstr ""
#~ msgid ""
diff --git a/locale/pt/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po b/locale/pt/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
index a7e3382..c85754b 100644
--- a/locale/pt/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
+++ b/locale/pt/LC_MESSAGES/_articles/2021-01-26-ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools.po
@@ -269,9 +269,9 @@ msgstr ""
msgid ""
"For my personal use, I've [packaged](https://git.euandreh.xyz/package-"
-"repository/) `remembering` for GNU Guix and Nix. Packaging it to any "
-"other distribution should be trivial, or just downloading the tarball and "
-"running `[sudo] make install`."
+"repository/) `remembering` for GNU Guix and Nix. Packaging it to any other "
+"distribution should be trivial, or just downloading the tarball and running "
+"`[sudo] make install`."
msgstr ""
#~ msgid ""
@@ -288,8 +288,8 @@ msgstr ""
#~ msgid ""
#~ "Today I pushed v0.1.0 of "
-#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to "
-#~ "enhance the interactive usability of menu-like tools, such as "
+#~ "[remembering](https://git.euandreh.xyz/remembering/), a tool to enhance the "
+#~ "interactive usability of menu-like tools, such as "
#~ "[dmenu](https://tools.suckless.org/dmenu/) and "
#~ "[fzf](https://github.com/junegunn/fzf)."
#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po b/locale/pt/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
index 442e6d0..e30c889 100644
--- a/locale/pt/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
+++ b/locale/pt/LC_MESSAGES/_articles/2021-02-17-ann-fallible-fault-injection-library-for-stress-testing-failure-scenarios.po
@@ -241,25 +241,6 @@ msgid ""
msgstr ""
msgid ""
-"--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
-"+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
-"@@ -1,11 +1,11 @@\n"
-" bool a_function() {\n"
-"- char *s1 = malloc(A_NUMBER);\n"
-"+ char *s1 = MALLOC(A_NUMBER);\n"
-" if (!s1) {\n"
-" return false;\n"
-" }\n"
-" strcpy(s1, \"some string\");\n"
-"\n"
-"- char *s2 = malloc(A_NUMBER);\n"
-"+ char *s2 = MALLOC(A_NUMBER);\n"
-" if (!s2) {\n"
-" free(s1);\n"
-" return false;\n"
-msgstr ""
-
-msgid ""
"With this change, if the program gets compiled with the `-DFALLIBLE` flag "
"the fault-injection mechanism will run, and `MALLOC` will fail once for each"
" `filename`+`lineno` combination. When the flag is missing, `MALLOC` is a "
@@ -342,3 +323,41 @@ msgstr ""
msgid "Patches welcome!"
msgstr ""
+
+msgid ""
+"--- 3.c 2021-02-17 00:15:38.019706074 -0300\n"
+"+++ 4.c 2021-02-17 00:44:32.306885590 -0300\n"
+"@@ -1,11 +1,11 @@\n"
+" bool a_function() {\n"
+"- char *s1 = malloc(A_NUMBER);\n"
+"+ char *s1 = MALLOC(A_NUMBER);\n"
+" if (!s1) {\n"
+" return false;\n"
+" }\n"
+" strcpy(s1, \"some string\");\n"
+"\n"
+"- char *s2 = malloc(A_NUMBER);\n"
+"+ char *s2 = MALLOC(A_NUMBER);\n"
+" if (!s2) {\n"
+" free(s1);\n"
+" return false;\n"
+msgstr ""
+
+#~ msgid ""
+#~ "--- 3.c\t2021-02-17 00:15:38.019706074 -0300\n"
+#~ "+++ 4.c\t2021-02-17 00:44:32.306885590 -0300\n"
+#~ "@@ -1,11 +1,11 @@\n"
+#~ " bool a_function() {\n"
+#~ "- char *s1 = malloc(A_NUMBER);\n"
+#~ "+ char *s1 = MALLOC(A_NUMBER);\n"
+#~ " if (!s1) {\n"
+#~ " return false;\n"
+#~ " }\n"
+#~ " strcpy(s1, \"some string\");\n"
+#~ "\n"
+#~ "- char *s2 = malloc(A_NUMBER);\n"
+#~ "+ char *s2 = MALLOC(A_NUMBER);\n"
+#~ " if (!s2) {\n"
+#~ " free(s1);\n"
+#~ " return false;\n"
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po b/locale/pt/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
new file mode 100644
index 0000000..f6e087b
--- /dev/null
+++ b/locale/pt/LC_MESSAGES/_pastebins/2021-04-03-javascript-naive-slugify.po
@@ -0,0 +1,70 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: JavaScript naive slugify"
+msgstr ""
+
+msgid "date: 2021-04-03"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: javascript-naive-slugify"
+msgstr ""
+
+msgid ""
+"const s = \"Pézão: açaí, saci-pererê.\";\n"
+"\n"
+"function slugify(s) {\n"
+" return s\n"
+" .toLowerCase()\n"
+" .replaceAll(\":\", \"\")\n"
+" .replaceAll(\".\", \"\")\n"
+" .replaceAll(\",\", \"\")\n"
+" .replaceAll(\"-\", \"\")\n"
+" .replaceAll(\"á\", \"a\")\n"
+" .replaceAll(\"ã\", \"a\")\n"
+" .replaceAll(\"à\", \"a\")\n"
+" .replaceAll(\"é\", \"e\")\n"
+" .replaceAll(\"ê\", \"e\")\n"
+" .replaceAll(\"í\", \"i\")\n"
+" .replaceAll(\"ó\", \"o\")\n"
+" .replaceAll(\"ô\", \"o\")\n"
+" .replaceAll(\"ú\", \"u\")\n"
+" .replaceAll(\"ü\", \"u\")\n"
+" .replaceAll(\"ç\", \"c\");\n"
+"}\n"
+"\n"
+"console.log(slugify(s));\n"
+msgstr ""
+
+#~ msgid ""
+#~ "const s = \"Pézão: açaí, saci-pererê.\";\n"
+#~ "\n"
+#~ "function slugify(s) {\n"
+#~ " return s\n"
+#~ " .toLowerCase()\n"
+#~ " .replaceAll(\":\", \"\")\n"
+#~ " .replaceAll(\".\", \"\")\n"
+#~ " .replaceAll(\",\", \"\")\n"
+#~ " .replaceAll(\"-\", \"\")\n"
+#~ " .replaceAll(\"á\", \"a\")\n"
+#~ " .replaceAll(\"ã\", \"a\")\n"
+#~ " .replaceAll(\"à\", \"a\")\n"
+#~ " .replaceAll(\"é\", \"e\")\n"
+#~ " .replaceAll(\"ê\", \"e\")\n"
+#~ " .replaceAll(\"í\", \"i\")\n"
+#~ " .replaceAll(\"ó\", \"o\")\n"
+#~ " .replaceAll(\"ô\", \"o\")\n"
+#~ " .replaceAll(\"ú\", \"u\")\n"
+#~ " .replaceAll(\"ü\", \"u\")\n"
+#~ " .replaceAll(\"ç\", \"c\");\n"
+#~ "}\n"
+#~ "\n"
+#~ "console.log(slugify(s));\n"
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po b/locale/pt/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
index badc41e..d0e9b44 100644
--- a/locale/pt/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
+++ b/locale/pt/LC_MESSAGES/_screencasts/2021-02-07-autoqemu-automate-installation-and-ssh-setup-of-iso-os-images.po
@@ -57,14 +57,6 @@ msgid "It assumes that `$HOME/.local/bin` is in `$PATH`."
msgstr ""
msgid ""
-"This screencast is a simple demo of automating the installation of Alpine "
-"Linux 3.12.3 standard x86_64 with "
-"[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more "
-"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
-"Makefiles glued together."
-msgstr ""
-
-msgid ""
"pushd `mktemp -d`\n"
"git clone https://git.euandreh.xyz/autoqemu .\n"
"make\n"
@@ -72,6 +64,22 @@ msgid ""
"autoqemu ssh alpine\n"
msgstr ""
+msgid ""
+"This screencast is a simple demo of automating the installation of Alpine "
+"Linux 3.12.3 standard x86_64 with "
+"[AutoQEMU](https://git.euandreh.xyz/autoqemu/about), which is nothing more "
+"than POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+"Makefiles glued together."
+msgstr ""
+
+#~ msgid ""
+#~ "This screencast is a simple demo of automating the installation of Alpine "
+#~ "Linux 3.12.3 standard x86_64 with "
+#~ "[AutoQEMU](https://git.euandreh.xyz/autoqemu/), which is nothing more than "
+#~ "POSIX sh, [expect](https://core.tcl-lang.org/expect/index) scripts and "
+#~ "Makefiles glued together."
+#~ msgstr ""
+
#~ msgid ""
#~ "pushd `mktemp -d`\n"
#~ "git clone https://git.euandreh.xyz/autoqemu .\n"
diff --git a/locale/pt/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po b/locale/pt/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
index 421e295..6030e0c 100644
--- a/locale/pt/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
+++ b/locale/pt/LC_MESSAGES/_tils/2020-08-14-browse-a-git-repository-at-a-specific-commit.po
@@ -49,9 +49,6 @@ msgid ""
"current staging area back to what it was before the checkout."
msgstr ""
-msgid "References:"
-msgstr ""
-
msgid ""
"[GIT: Checkout to a specific folder](https://stackoverflow.com/a/16493707) "
"(StackOverflow)"
@@ -107,6 +104,12 @@ msgstr ""
msgid "eu_categories: git"
msgstr ""
+msgid "References"
+msgstr ""
+
+#~ msgid "References:"
+#~ msgstr ""
+
#~ msgid ""
#~ "title: Browse a git repository at a specific commit\n"
#~ "date: 2020-08-14\n"
diff --git a/locale/pt/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po b/locale/pt/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
index 182061b..1610cea 100644
--- a/locale/pt/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
+++ b/locale/pt/LC_MESSAGES/_tils/2020-09-05-pull-requests-with-git-the-old-school-way.po
@@ -25,9 +25,9 @@ msgid ""
"The only difference is that you're working with only Git itself, so you're "
"not tied to any Git hosting provider: you can send pull requests across them"
" transparently! You could even use your own "
-"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked"
-" in by any of them, putting the \"D\" back in \"DVCS\": it's a "
-"**distributed** version control system."
+"[cgit](https://git.zx2c4.com/cgit/) installation. No need to be locked in by"
+" any of them, putting the \"D\" back in \"DVCS\": it's a **distributed** "
+"version control system."
msgstr ""
msgid "`git request-pull` introduction"
diff --git a/locale/pt/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po b/locale/pt/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
new file mode 100644
index 0000000..ab59a4f
--- /dev/null
+++ b/locale/pt/LC_MESSAGES/_tils/2021-04-24-clojure-auto-curry.po
@@ -0,0 +1,220 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Clojure auto curry"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: clojure-auto-curry"
+msgstr ""
+
+msgid "A naive `add` definition, alongside its usage and macroexpansion:"
+msgstr ""
+
+msgid ""
+"user=> (defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))\n"
+"#'user/add\n"
+"\n"
+"user=> (add 1)\n"
+"#object[clojure.core$partial$fn__5857 0x2c708440 \"clojure.core$partial$fn__5857@2c708440\"]\n"
+"\n"
+"user=> (add 1 2 3 4)\n"
+"#object[clojure.core$partial$fn__5863 0xf4c0e4e \"clojure.core$partial$fn__5863@f4c0e4e\"]\n"
+"\n"
+"user=> ((add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"user=> (((add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"user=> (use 'clojure.pprint)\n"
+"nil\n"
+"\n"
+"user=> (pprint\n"
+" (macroexpand\n"
+" '(defcurry add\n"
+" [a b c d e]\n"
+" (+ 1 2 3 4 5))))\n"
+"(def\n"
+" add\n"
+" (clojure.core/fn\n"
+" ([a b c d e] (+ 1 2 3 4 5))\n"
+" ([a] (clojure.core/partial add a))\n"
+" ([a b] (clojure.core/partial add a b))\n"
+" ([a b c] (clojure.core/partial add a b c))\n"
+" ([a b c d] (clojure.core/partial add a b c d))))\n"
+"nil\n"
+msgstr ""
+
+msgid ""
+"This simplistic `defcurry` definition doesn't support optional parameters, "
+"multi-arity, `&` rest arguments, docstrings, etc., but it could certainly "
+"evolve to do so."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Same Clojure as before, now with auto-currying via macros."
+msgstr ""
+
+msgid ""
+"Here's a simple macro defined by [Loretta "
+"He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+"create Clojure functions that are curried on all arguments, relying on "
+"Clojure's multi-arity support:"
+msgstr ""
+
+msgid "date: 2021-04-24 1"
+msgstr ""
+
+msgid ""
+"(defmacro defcurry\n"
+" [name args & body]\n"
+" (let [partials (map (fn [n]\n"
+" `(~(subvec args 0 n) (partial ~name ~@(take n args))))\n"
+" (range 1 (count args)))]\n"
+" `(defn ~name\n"
+" (~args ~@body)\n"
+" ~@partials)))\n"
+msgstr ""
+
+msgid "Comparison with Common Lisp"
+msgstr ""
+
+msgid "My attempt at writing an equivalent for Common Lisp gives me:"
+msgstr ""
+
+msgid ""
+"(defun partial (fn &rest args)\n"
+" (lambda (&rest args2)\n"
+" (apply fn (append args args2))))\n"
+"\n"
+"(defun curry-n (n func)\n"
+" (cond ((< n 0) (error \"Too many arguments\"))\n"
+" ((zerop n) (funcall func))\n"
+" (t (lambda (&rest rest)\n"
+" (curry-n (- n (length rest))\n"
+" (apply #'partial func rest))))))\n"
+"\n"
+"(defmacro defcurry (name args &body body)\n"
+" `(defun ,name (&rest rest)\n"
+" (let ((func (lambda ,args ,@body)))\n"
+" (curry-n (- ,(length args) (length rest))\n"
+" (apply #'partial func rest)))))\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "The usage is pretty similar:"
+msgstr ""
+
+msgid ""
+"* (defcurry add (a b c d e)\n"
+" (+ a b c d e))\n"
+"ADD\n"
+"\n"
+"* (add 1)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216419B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4)\n"
+"#<FUNCTION (LAMBDA (&REST REST) :IN CURRY-N) {100216537B}>\n"
+"\n"
+"* (funcall (add 1) 2 3 4 5)\n"
+"15\n"
+"\n"
+"* (funcall (funcall (add 1) 2 3) 4 5)\n"
+"15\n"
+"\n"
+"* (macroexpand-1\n"
+" '(defcurry add (a b c d e)\n"
+" (+ a b c d e)))\n"
+"(DEFUN ADD (&REST REST)\n"
+" (LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E))))\n"
+" (CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST))))\n"
+"T\n"
+msgstr ""
+
+msgid ""
+"This also require `funcall`s, since we return a `lambda` that doesn't live "
+"in the function namespace."
+msgstr ""
+
+msgid ""
+"Like the Clojure one, it doesn't support optional parameters, `&rest` rest "
+"arguments, docstrings, etc., but it also could evolve to do so."
+msgstr ""
+
+msgid "updated_at: 2021-04-27"
+msgstr ""
+
+#~ msgid ""
+#~ "(defmacro defcurry\n"
+#~ " [fname args & body]\n"
+#~ " (let [partials (map (fn [n]\n"
+#~ " `(~(subvec args 0 n) (partial ~fname ~@(take n args))))\n"
+#~ " (range 1 (count args)))]\n"
+#~ " `(defn ~fname\n"
+#~ " (~args ~@body)\n"
+#~ " ~@partials)))\n"
+#~ msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "A simple macro defined by [Loretta "
+#~ "He](http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry) to "
+#~ "create Clojure functions that are curried on all arguments, relying on "
+#~ "Clojure's multi-arity support:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Without built-in multi-arity support, we have to do more work, like tracking"
+#~ " the number of arguments consumed so far. That is, without dependending on "
+#~ "any library, sticking to ANSI Common Lisp."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "(defun curry-n (n fn)\n"
+#~ " (if (= 0 n)\n"
+#~ " (funcall fn)\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (curry-n (something n) fn))))\n"
+#~ "\n"
+#~ "(defun add (a b c d e)\n"
+#~ " (curry-n\n"
+#~ " (length '(a b c d e))\n"
+#~ " (lambda (&rest rest)\n"
+#~ " (apply #'+ rest))))\n"
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po b/locale/pt/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
new file mode 100644
index 0000000..6aa66a8
--- /dev/null
+++ b/locale/pt/LC_MESSAGES/_tils/2021-04-24-common-lisp-argument-precedence-order-parameterization-of-a-generic-function.po
@@ -0,0 +1,210 @@
+#
+msgid ""
+msgstr ""
+
+msgid ""
+"title: Common Lisp argument precedence order parameterization of a generic "
+"function"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid ""
+"ref: common-lisp-argument-precedence-order-parameterization-of-a-generic-"
+"function"
+msgstr ""
+
+msgid ""
+"When CLOS dispatches a method, it picks the most specific method definition "
+"to the argument list:"
+msgstr ""
+
+msgid ""
+"\n"
+"* (defgeneric a-fn (x))\n"
+"#<STANDARD-GENERIC-FUNCTION A-FN (0) {5815ACB9}>\n"
+"\n"
+"* (defmethod a-fn (x) :default-method)\n"
+"#<STANDARD-METHOD A-FN (T) {581DB535}>\n"
+"\n"
+"* (defmethod a-fn ((x number)) :a-number)\n"
+"#<STANDARD-METHOD A-FN (NUMBER) {58241645}>\n"
+"\n"
+"* (defmethod a-fn ((x (eql 1))) :number-1)\n"
+"#<STANDARD-METHOD A-FN ((EQL 1)) {582A7D75}>\n"
+"\n"
+"* (a-fn nil)\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn \"1\")\n"
+":DEFAULT-METHOD\n"
+"\n"
+"* (a-fn 0)\n"
+":A-NUMBER\n"
+"\n"
+"* (a-fn 1)\n"
+":NUMBER-1\n"
+msgstr ""
+
+msgid ""
+"CLOS uses a similar logic when choosing the method from parent classes, when"
+" multiple ones are available:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-A {583E0B25}>\n"
+"* (defclass class-b () ())\n"
+"\n"
+"#<STANDARD-CLASS CLASS-B {583E7F6D}>\n"
+"* (defgeneric another-fn (obj))\n"
+"\n"
+"#<STANDARD-GENERIC-FUNCTION ANOTHER-FN (0) {583DA749}>\n"
+"* (defmethod another-fn ((obj class-a)) :class-a)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-A) {584523C5}>\n"
+"* (defmethod another-fn ((obj class-b)) :class-b)\n"
+"; Compiling LAMBDA (.PV-CELL. .NEXT-METHOD-CALL. OBJ):\n"
+"; Compiling Top-Level Form:\n"
+"\n"
+"#<STANDARD-METHOD ANOTHER-FN (CLASS-B) {584B8895}>\n"
+msgstr ""
+
+msgid ""
+"Given the above definitions, when inheriting from `class-a` and `class-b`, "
+"the order of inheritance matters:"
+msgstr ""
+
+msgid ""
+"* (defclass class-a-coming-first (class-a class-b) ())\n"
+"#<STANDARD-CLASS CLASS-A-COMING-FIRST {584BE6AD}>\n"
+"\n"
+"* (defclass class-b-coming-first (class-b class-a) ())\n"
+"#<STANDARD-CLASS CLASS-B-COMING-FIRST {584C744D}>\n"
+"\n"
+"* (another-fn (make-instance 'class-a-coming-first))\n"
+":CLASS-A\n"
+"\n"
+"* (another-fn (make-instance 'class-b-coming-first))\n"
+":CLASS-B\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (0) {584D9EC9}>\n"
+"\n"
+"* (defmethod yet-another-fn ((obj1 class-a) obj2) :first-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (CLASS-A T) {5854269D}>\n"
+"\n"
+"* (defmethod yet-another-fn (obj1 (obj2 class-b)) :second-arg-specialized)\n"
+"#<STANDARD-METHOD YET-ANOTHER-FN (T CLASS-B) {585AAAAD}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":FIRST-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"For that, we use the `:argument-precedence-order` option when declaring a "
+"generic function:"
+msgstr ""
+
+msgid ""
+"* (defgeneric yet-another-fn (obj1 obj2) (:argument-precedence-order obj2 obj1))\n"
+"#<STANDARD-GENERIC-FUNCTION YET-ANOTHER-FN (2) {584D9EC9}>\n"
+"\n"
+"* (yet-another-fn (make-instance 'class-a) (make-instance 'class-b))\n"
+":SECOND-ARG-SPECIALIZED\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Comparison with Clojure"
+msgstr ""
+
+msgid "Clojure has an equivalent, when using `defmulti`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Conclusion"
+msgstr ""
+
+msgid ""
+"Making the argument precedence order configurable for generic functions but "
+"not for class definitions makes a lot of sense."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "TIL."
+msgstr ""
+
+msgid ""
+"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?"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid ""
+"[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"
+msgstr ""
+
+msgid "date: 2021-04-24 2"
+msgstr ""
+
+#~ msgid "date: 2021-04-24"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 to the"
+#~ " choice to be based on the second argument first?"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "When declaring a class, we can choose the precedence order, and that is "
+#~ "about it. But when defining a generic function, the order of argumentws is "
+#~ "more important to the function semantics, and the argument precedence being "
+#~ "left-to-right is just the default behaviour."
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po b/locale/pt/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
new file mode 100644
index 0000000..925a00b
--- /dev/null
+++ b/locale/pt/LC_MESSAGES/_tils/2021-04-24-three-way-conditional-for-number-signs.po
@@ -0,0 +1,95 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: Three-way conditional for number signs"
+msgstr ""
+
+msgid "date: 2021-04-24 3"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: three-way-conditional-for-number-signs"
+msgstr ""
+
+msgid ""
+"A useful macro from Paul Graham's [On "
+"Lisp](http://www.paulgraham.com/onlisptext.html) book:"
+msgstr ""
+
+msgid ""
+"(defmacro nif (expr pos zero neg)\n"
+" (let ((g (gensym)))\n"
+" `(let ((,g ,expr))\n"
+" (cond ((plusp ,g) ,pos)\n"
+" ((zerop ,g) ,zero)\n"
+" (t ,neg)))))\n"
+msgstr ""
+
+msgid ""
+"The latest example I can think of is section 1.3.3 of [Structure and "
+"Interpretation of Computer "
+"Programs](https://mitpress.mit.edu/sites/default/files/sicp/index.html), "
+"which I was reading recently:"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (let ((test-value (f midpoint)))\n"
+" (cond ((positive? test-value)\n"
+" (search f neg-point midpoint))\n"
+" ((negative? test-value)\n"
+" (search f midpoint pos-point))\n"
+" (else midpoint))))))\n"
+msgstr ""
+
+msgid ""
+"(define (search f neg-point pos-point)\n"
+" (let ((midpoint (average neg-point pos-point)))\n"
+" (if (close-enough? neg-point post-point)\n"
+" midpoint\n"
+" (nif (f midpoint)\n"
+" (search f neg-point midpoint)\n"
+" (midpoint)\n"
+" (search f midpoint pos-point)))))\n"
+msgstr ""
+
+msgid ""
+"It also avoids `cond`'s extra clunky parentheses for grouping, which is "
+"unnecessary but built-in."
+msgstr ""
+
+msgid ""
+"As a macro, I personally feel it tilts the balance towards expressivenes "
+"despite its extra cognitive load toll."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+#~ msgid ""
+#~ "After I looked at this macro, I started seeing opportunities to using it in "
+#~ "many places, and yet I didn't see anyonelse using it."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Not that the book should introduce such macro this early, but I couldn't "
+#~ "avoid feeling bothered by not using a `nif` macro, which could even remove "
+#~ "the need for the intermediate `test-value` variable:"
+#~ msgstr ""