From mboxrd@z Thu Jan 1 00:00:00 1970 From: taylanbayirli@gmail.com (Taylan Ulrich =?utf-8?Q?Bay=C4=B1rl=C4=B1?= =?utf-8?Q?=2FKammer?=) Subject: Some macros to make package definitions prettier Date: Wed, 25 Feb 2015 17:42:23 +0100 Message-ID: <874mqa6iz4.fsf@taylan.uni.cx> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:59892) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YQf2c-0001yO-87 for guix-devel@gnu.org; Wed, 25 Feb 2015 11:42:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YQf2a-0005Oh-V9 for guix-devel@gnu.org; Wed, 25 Feb 2015 11:42:30 -0500 Received: from mail-wi0-x233.google.com ([2a00:1450:400c:c05::233]:63380) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YQf2a-0005OK-Nm for guix-devel@gnu.org; Wed, 25 Feb 2015 11:42:28 -0500 Received: by mail-wi0-f179.google.com with SMTP id ex7so6467466wid.0 for ; Wed, 25 Feb 2015 08:42:28 -0800 (PST) Received: from taylan.uni.cx (p200300514A2BB80C0213E8FFFEED36FB.dip0.t-ipconnect.de. [2003:51:4a2b:b80c:213:e8ff:feed:36fb]) by mx.google.com with ESMTPSA id y14sm52452218wjr.39.2015.02.25.08.42.27 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Feb 2015 08:42:27 -0800 (PST) List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org To: guix-devel@gnu.org 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