From: "Thompson, David" <dthompson2@worcester.edu>
To: "Taylan Ulrich Bayırlı/Kammer" <taylanbayirli@gmail.com>
Cc: guix-devel <guix-devel@gnu.org>
Subject: Re: Some macros to make package definitions prettier
Date: Wed, 25 Feb 2015 12:04:31 -0500 [thread overview]
Message-ID: <CAJ=RwfaVe-7Q5gV-487NeWD_TBhiWZA8jrUaeyhoo12yXZV8ZA@mail.gmail.com> (raw)
In-Reply-To: <874mqa6iz4.fsf@taylan.uni.cx>
On Wed, Feb 25, 2015 at 11:42 AM, Taylan Ulrich Bayırlı/Kammer
<taylanbayirli@gmail.com> wrote:
> I would propose the following macros to make package definitions
> somewhat nicer:
I've been thinking that we need some macros for this for awhile!
Thanks for getting the conversation started.
>
> ;;; modify-phases
>
> (define-syntax modify-phases
> (syntax-rules ()
> ((modify-phases phases mod-spec ...)
> (let* ((phases* phases)
> (phases* (%modify-phases phases* mod-spec))
> ...)
> phases*))))
>
> (define-syntax %modify-phases
> (syntax-rules (delete replace add-before add-after)
> ((_ phases (delete old-phase-name))
> (alist-delete 'old-phase-name phases))
> ((_ phases (replace old-phase-name new-phase))
> (alist-replace 'old-phase-name new-phase phases))
> ((_ phases (add-before old-phase-name new-phase-name new-phase))
> (alist-cons-before 'old-phase-name 'new-phase-name new-phase phases))
> ((_ phases (add-after old-phase-name new-phase-name new-phase))
> (alist-cons-after 'old-phase-name 'new-phase-name new-phase phases))))
>
> ;;; Usage example:
>
> (modify-phases '((foo . 0) (bar . 1) (baz . 2))
> (delete foo)
> (replace bar 'x)
> (add-before baz pre-baz 'y)) ;=> ((bar . x) (pre-baz . y) (baz . 2))
>
>
> This has the following advantages:
>
> - The order in which the phases are modified is top-down, where in our
> current style it's bottom-up which both distracts (IMO), and one may
> forget, as the chain grows and one forgets that it's indeed just a
> chain of function calls like (foo (bar (baz x))).
>
> - Indentation doesn't keep growing as one adds more modifications.
>
> - It's easier for Scheme-newcomers, though one might say alists are
> pretty simple and fundamental and should be learned immediately...
I like the top-down ordering and the linear structure rather than a
nested structure like we have currently.
I understand the temptation to name it 'modify-phases', but since this
macro applies to any alist, I think 'modify-alist' or something with
"alist" in the name would be more appropriate.
>
> And secondly:
>
> ;;; phase-lambda
>
> (define-syntax phase-lambda
> (syntax-rules ()
> ((phase-lambda ((arg (alist-entry ...))
> ...)
> body ...)
> (lambda* (#:key arg ... #:allow-other-keys)
> (let-values (((alist-entry ...)
> (let ((arg* arg))
> (values
> (assoc-ref arg* (symbol->string 'alist-entry))
> ...)))
> ...)
> body ...)))))
>
> ;;; Usage example:
>
> (phase-lambda ((inputs (libx liby))
> (outputs (out)))
> ...)
>
> ;;; effectively equivalent to:
>
> (lambda* (#:key inputs outputs #:allow-other-keys)
> (let ((libx (assoc-ref inputs "libx"))
> (liby (assoc-ref inputs "liby"))
> (out (assoc-ref outputs "out")))
> ...))
>
>
> This saves the usual boilerplate of '(#:key inputs outputs
> #:allow-other-keys)' and the subsequent `assoc-ref' uses. One might say
> it's too specific because the phase procedures also receive non-alist
> arguments (although one can add an argument clause like '(foo ())' and
> it will work because no `assoc-ref' call will happen on `foo', though
> that's a hack), but I looked at all occurrences of "#:key" in
> gnu/packages/*.scm, and pure uses of `input' and/or `output' are
> extremely dominant, such that it should be fine to fall back to a plain
> `lambda*' in the remaining cases.
I'm not sure I like combining the alist destructuring part of this
macro. IMO, 'phase-lambda' could just take care of the 'lambda*'
boilerplate, and maybe another macro ('alist-let'?) to reduce the
'assoc-ref' usage.
Implementation details aside, I think macros like these are very much
needed to reduce boilerplate and improve the readability of our
package recipes.
Thanks for sharing!
next prev parent reply other threads:[~2015-02-25 17:04 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-25 16:42 Some macros to make package definitions prettier Taylan Ulrich Bayırlı/Kammer
2015-02-25 17:04 ` Thompson, David [this message]
2015-02-25 17:06 ` Thompson, David
2015-02-25 19:27 ` Taylan Ulrich Bayırlı/Kammer
2015-02-25 20:54 ` Taylan Ulrich Bayırlı/Kammer
2015-02-25 18:12 ` Andreas Enge
2015-02-25 19:46 ` Taylan Ulrich Bayırlı/Kammer
2015-02-25 20:24 ` Thompson, David
2015-02-25 23:32 ` Ludovic Courtès
2015-02-26 11:07 ` Taylan Ulrich Bayırlı/Kammer
2015-02-26 21:39 ` Ludovic Courtès
2015-03-03 16:49 ` Taylan Ulrich Bayırlı/Kammer
2015-03-03 20:44 ` Ludovic Courtès
2015-03-03 22:47 ` Taylan Ulrich Bayırlı/Kammer
2015-03-04 9:52 ` Ludovic Courtès
2015-02-26 21:41 ` Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAJ=RwfaVe-7Q5gV-487NeWD_TBhiWZA8jrUaeyhoo12yXZV8ZA@mail.gmail.com' \
--to=dthompson2@worcester.edu \
--cc=guix-devel@gnu.org \
--cc=taylanbayirli@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.