monads: Add 'mparameterize'.

* etc/system-tests.scm (mparameterize): Move to...
* guix/monads.scm (mparameterize): ... here.
* tests/monads.scm ("mparameterize"): New test.
* .dir-locals.el (c-mode): Add it.
This commit is contained in:
Ludovic Courtès 2022-07-10 12:39:44 +02:00
parent bf0a646a5b
commit 9fdc4b6c28
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
4 changed files with 32 additions and 17 deletions

View file

@ -118,6 +118,7 @@
(eval . (put 'munless 'scheme-indent-function 1)) (eval . (put 'munless 'scheme-indent-function 1))
(eval . (put 'mlet* 'scheme-indent-function 2)) (eval . (put 'mlet* 'scheme-indent-function 2))
(eval . (put 'mlet 'scheme-indent-function 2)) (eval . (put 'mlet 'scheme-indent-function 2))
(eval . (put 'mparameterize 'scheme-indent-function 2))
(eval . (put 'run-with-store 'scheme-indent-function 1)) (eval . (put 'run-with-store 'scheme-indent-function 1))
(eval . (put 'run-with-state 'scheme-indent-function 1)) (eval . (put 'run-with-state 'scheme-indent-function 1))
(eval . (put 'wrap-program 'scheme-indent-function 1)) (eval . (put 'wrap-program 'scheme-indent-function 1))

View file

@ -43,21 +43,6 @@ (define (source-commit directory)
(repository-close! repository)) (repository-close! repository))
#f)))) #f))))
(define-syntax mparameterize
(syntax-rules ()
"This form implements dynamic scoping, similar to 'parameterize', but in a
monadic context."
((_ monad ((parameter value) rest ...) body ...)
(let ((old-value (parameter)))
(mbegin monad
;; XXX: Non-local exits are not correctly handled.
(return (parameter value))
(mlet monad ((result (mparameterize monad (rest ...) body ...)))
(parameter old-value)
(return result)))))
((_ monad () body ...)
(mbegin monad body ...))))
(define (tests-for-current-guix source commit) (define (tests-for-current-guix source commit)
"Return a list of tests for perform, using Guix built from SOURCE, a channel "Return a list of tests for perform, using Guix built from SOURCE, a channel
instance." instance."

View file

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2017 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013, 2014, 2015, 2017, 2022 Ludovic Courtès <ludo@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -40,6 +40,7 @@ (define-module (guix monads)
mbegin mbegin
mwhen mwhen
munless munless
mparameterize
lift0 lift1 lift2 lift3 lift4 lift5 lift6 lift7 lift lift0 lift1 lift2 lift3 lift4 lift5 lift6 lift7 lift
listm listm
foldm foldm
@ -398,6 +399,21 @@ (define-syntax munless
(mbegin %current-monad (mbegin %current-monad
mexp0 mexp* ...))))) mexp0 mexp* ...)))))
(define-syntax mparameterize
(syntax-rules ()
"This form implements dynamic scoping, similar to 'parameterize', but in a
monadic context."
((_ monad ((parameter value) rest ...) body ...)
(let ((old-value (parameter)))
(mbegin monad
;; XXX: Non-local exits are not correctly handled.
(return (parameter value))
(mlet monad ((result (mparameterize monad (rest ...) body ...)))
(parameter old-value)
(return result)))))
((_ monad () body ...)
(mbegin monad body ...))))
(define-syntax define-lift (define-syntax define-lift
(syntax-rules () (syntax-rules ()
((_ liftn (args ...)) ((_ liftn (args ...))

View file

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013, 2014, 2015, 2016, 2022 Ludovic Courtès <ludo@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -137,6 +137,19 @@ (define (g x)
%monads %monads
%monad-run)) %monad-run))
(test-assert "mparameterize"
(let ((parameter (make-parameter 'outside)))
(every (lambda (monad run)
(equal?
(run (mlet monad ((outer (return (parameter)))
(inner
(mparameterize monad ((parameter 'inside))
(return (parameter)))))
(return (list outer inner (parameter)))))
'(outside inside outside)))
%monads
%monad-run)))
(test-assert "mlet* + text-file + package-file" (test-assert "mlet* + text-file + package-file"
(run-with-store %store (run-with-store %store
(mlet* %store-monad ((guile (package-file %bootstrap-guile "bin/guile")) (mlet* %store-monad ((guile (package-file %bootstrap-guile "bin/guile"))