diff options
author | Marius Bakke <mbakke@fastmail.com> | 2019-11-15 20:11:35 +0100 |
---|---|---|
committer | Marius Bakke <mbakke@fastmail.com> | 2019-11-15 20:11:35 +0100 |
commit | f056553c6b8ffa36f4ce9fb1c3602a8f4b1de242 (patch) | |
tree | 80c815216a3717cf00b615c9cb8840c113eaf79f /gnu/services.scm | |
parent | 2c9d34166983565120f831284df57a07e2edd2f9 (diff) | |
parent | 528b52390d216d8a8cd13dfcd1e6e40a6448e6c2 (diff) | |
download | guix-f056553c6b8ffa36f4ce9fb1c3602a8f4b1de242.tar.gz guix-f056553c6b8ffa36f4ce9fb1c3602a8f4b1de242.zip |
Merge branch 'master' into staging
Diffstat (limited to 'gnu/services.scm')
-rw-r--r-- | gnu/services.scm | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/gnu/services.scm b/gnu/services.scm index 6ee05d4580..394470ba7d 100644 --- a/gnu/services.scm +++ b/gnu/services.scm @@ -775,18 +775,34 @@ TARGET-TYPE; return the root service adjusted accordingly." (eq? (service-kind service) target-type)) services) ((sink) - (let loop ((sink sink)) - (let* ((dependents (map loop (dependents sink))) - (extensions (map (apply-extension sink) dependents)) - (extend (service-type-extend (service-kind sink))) - (compose (service-type-compose (service-kind sink))) - (params (service-value sink))) - ;; We distinguish COMPOSE and EXTEND because PARAMS typically has a - ;; different type than the elements of EXTENSIONS. - (if extend - (service (service-kind sink) - (extend params (compose extensions))) - sink)))) + ;; Use the state monad to keep track of already-visited services in the + ;; graph and to memoize their value once folded. + (run-with-state + (let loop ((sink sink)) + (mlet %state-monad ((visited (current-state))) + (match (vhash-assq sink visited) + (#f + (mlet* %state-monad + ((dependents (mapm %state-monad loop (dependents sink))) + (visited (current-state)) + (extensions -> (map (apply-extension sink) dependents)) + (extend -> (service-type-extend (service-kind sink))) + (compose -> (service-type-compose (service-kind sink))) + (params -> (service-value sink)) + (service + -> + ;; Distinguish COMPOSE and EXTEND because PARAMS typically + ;; has a different type than the elements of EXTENSIONS. + (if extend + (service (service-kind sink) + (extend params (compose extensions))) + sink))) + (mbegin %state-monad + (set-current-state (vhash-consq sink service visited)) + (return service)))) + ((_ . service) ;SINK was already visited + (return service))))) + vlist-null)) (() (raise (condition (&missing-target-service-error |