diff options
author | EuAndreh <eu@euandre.org> | 2025-03-31 21:51:40 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-03-31 21:51:40 -0300 |
commit | 570ec471d1605318aeefb030cd78682ae442235b (patch) | |
tree | 51e17eabe37c6689f8799b55e6875c3480329a2c /src/content/tils/2021/04/24/clojure-autocurry.adoc | |
parent | Makefile, mkdeps.sh: Derive index.html and feed.xml from more static "sortdat... (diff) | |
download | euandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.gz euandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.xz |
src/content/: Update all files left to asciidoc
Diffstat (limited to 'src/content/tils/2021/04/24/clojure-autocurry.adoc')
-rw-r--r-- | src/content/tils/2021/04/24/clojure-autocurry.adoc | 66 |
1 files changed, 32 insertions, 34 deletions
diff --git a/src/content/tils/2021/04/24/clojure-autocurry.adoc b/src/content/tils/2021/04/24/clojure-autocurry.adoc index c1e277f..d7dd557 100644 --- a/src/content/tils/2021/04/24/clojure-autocurry.adoc +++ b/src/content/tils/2021/04/24/clojure-autocurry.adoc @@ -1,22 +1,13 @@ ---- += Clojure auto curry -title: Clojure auto curry +:defcurry-orig: https://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry -date: 2021-04-24 1 +Here's a simple macro defined by {defcurry-orig}[Loretta He] to create Clojure +functions that are curried on all arguments, relying on Clojure's multi-arity +support: -updated_at: 2021-04-27 - -layout: post - -lang: en - -ref: clojure-auto-curry - ---- - -Here's a simple macro defined by [Loretta He][lorettahe] to create Clojure functions that are curried on all arguments, relying on Clojure's multi-arity support: - -```clojure +[source,clojure] +---- (defmacro defcurry [name args & body] (let [partials (map (fn [n] @@ -25,11 +16,12 @@ Here's a simple macro defined by [Loretta He][lorettahe] to create Clojure funct `(defn ~name (~args ~@body) ~@partials))) -``` +---- A naive `add` definition, alongside its usage and macroexpansion: -```clojure +[source,clojure] +---- user=> (defcurry add [a b c d e] (+ 1 2 3 4 5)) @@ -64,22 +56,24 @@ user=> (pprint ([a b c] (clojure.core/partial add a b c)) ([a b c d] (clojure.core/partial add a b c d)))) nil -``` +---- -This simplistic `defcurry` definition doesn't support optional parameters, multi-arity, `&` rest arguments, docstrings, etc., but it could certainly evolve to do so. +This simplistic `defcurry` definition doesn't support optional parameters, +multi-arity, `&` rest arguments, docstrings, etc., but it could certainly evolve +to do so. -I like how `defcurry` is so short, and abdicates the responsability of doing the multi-arity logic to Clojure's built-in multi-arity support. -Simple and elegant. +I like how `defcurry` is so short, and abdicates the responsability of doing the +multi-arity logic to Clojure's built-in multi-arity support. Simple and +elegant. Same Clojure as before, now with auto-currying via macros. -[lorettahe]: http://lorettahe.github.io/clojure/2016/09/22/clojure-auto-curry - -## Comparison with Common Lisp +== Comparison with Common Lisp My attempt at writing an equivalent for Common Lisp gives me: -```lisp +[source,lisp] +---- (defun partial (fn &rest args) (lambda (&rest args2) (apply fn (append args args2)))) @@ -96,15 +90,17 @@ My attempt at writing an equivalent for Common Lisp gives me: (let ((func (lambda ,args ,@body))) (curry-n (- ,(length args) (length rest)) (apply #'partial func rest))))) -``` +---- -Without built-in multi-arity support, we have to do more work, like tracking the number of arguments consumed so far. -We also have to write `#'partial` ourselves. -That is, without dependending on any library, sticking to ANSI Common Lisp. +Without built-in multi-arity support, we have to do more work, like tracking the +number of arguments consumed so far. We also have to write `#'partial` +ourselves. That is, without dependending on any library, sticking to ANSI +Common Lisp. The usage is pretty similar: -```lisp +[source,lisp] +---- * (defcurry add (a b c d e) (+ a b c d e)) ADD @@ -128,8 +124,10 @@ ADD (LET ((FUNC (LAMBDA (A B C D E) (+ A B C D E)))) (CURRY-N (- 5 (LENGTH REST)) (APPLY #'PARTIAL FUNC REST)))) T -``` +---- -This also require `funcall`s, since we return a `lambda` that doesn't live in the function namespace. +This also require `funcall`s, since we return a `lambda` that doesn't live in +the function namespace. -Like the Clojure one, it doesn't support optional parameters, `&rest` rest arguments, docstrings, etc., but it also could evolve to do so. +Like the Clojure one, it doesn't support optional parameters, `&rest` rest +arguments, docstrings, etc., but it also could evolve to do so. |