diff options
author | Ludovic Courtès <ludo@gnu.org> | 2015-06-08 22:49:50 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2015-06-08 23:00:49 +0200 |
commit | 751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd (patch) | |
tree | 2da2fcf7e6e300c98f2777e0bcb5670252ff4803 /guix | |
parent | ae9b96c7846cc7d4528da5c6d861d6440cf46e33 (diff) | |
download | gnu-guix-751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd.tar gnu-guix-751630c9c3f7f3e87dfccc5f5ba8cf61cdd6f8fd.tar.gz |
monads: Allow n-ary '>>=' expressions.
Suggested by Federico Beffa <beffa@fbengineering.ch>.
* guix/monads.scm (bind-syntax): New macro.
(with-monad): Use it instead of 'identifier-syntax'.
* tests/monads.scm (">>= with more than two arguments"): New test.
* doc/guix.texi (The Store Monad): Explain that there can be several MPROC.
Add an example.
Diffstat (limited to 'guix')
-rw-r--r-- | guix/monads.scm | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/guix/monads.scm b/guix/monads.scm index 4248525433..2196a9c991 100644 --- a/guix/monads.scm +++ b/guix/monads.scm @@ -112,6 +112,29 @@ (lambda (s) (syntax-violation 'return "return used outside of 'with-monad'" s))) +(define-syntax-rule (bind-syntax bind) + "Return a macro transformer that handles the expansion of '>>=' expressions +using BIND as the binary bind operator. + +This macro exists to allow the expansion of n-ary '>>=' expressions, even +though BIND is simply binary, as in: + + (with-monad %state-monad + (>>= (return 1) + (lift 1+ %state-monad) + (lift 1+ %state-monad))) +" + (lambda (stx) + (define (expand body) + (syntax-case body () + ((_ mval mproc) + #'(bind mval mproc)) + ((x mval mproc0 mprocs (... ...)) + (expand #'(>>= (>>= mval mproc0) + mprocs (... ...)))))) + + (expand stx))) + (define-syntax with-monad (lambda (s) "Evaluate BODY in the context of MONAD, and return its result." @@ -120,13 +143,13 @@ (eq? 'macro (syntax-local-binding #'monad)) ;; MONAD is a syntax transformer, so we can obtain the bind and return ;; methods by directly querying it. - #'(syntax-parameterize ((>>= (identifier-syntax (monad %bind))) + #'(syntax-parameterize ((>>= (bind-syntax (monad %bind))) (return (identifier-syntax (monad %return)))) body ...)) ((_ monad body ...) ;; MONAD refers to the <monad> record that represents the monad at run ;; time, so use the slow method. - #'(syntax-parameterize ((>>= (identifier-syntax + #'(syntax-parameterize ((>>= (bind-syntax (monad-bind monad))) (return (identifier-syntax (monad-return monad)))) |