all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: taylanbayirli@gmail.com (Taylan Ulrich Bayırlı/Kammer)
To: guix-devel@gnu.org
Subject: Some macros to make package definitions prettier
Date: Wed, 25 Feb 2015 17:42:23 +0100	[thread overview]
Message-ID: <874mqa6iz4.fsf@taylan.uni.cx> (raw)

I would propose the following macros to make package definitions
somewhat nicer:


;;; 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...


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.


WDYT?

Taylan

             reply	other threads:[~2015-02-25 16:42 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-25 16:42 Taylan Ulrich Bayırlı/Kammer [this message]
2015-02-25 17:04 ` Some macros to make package definitions prettier Thompson, David
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=874mqa6iz4.fsf@taylan.uni.cx \
    --to=taylanbayirli@gmail.com \
    --cc=guix-devel@gnu.org \
    /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.