Subject: Re: [PATCH] gexp: ‘with-parameters’properly handles ‘%graft?’.

From: David Elsing <[email-masked]>
Date: Tue, 25 Feb 2025 22:36:31 +0000

Hello,

Ludovic Courtès <[email-masked]> writes:

> +         (mcall-with-parameters
> +             parameters
> +             (map (lambda (thunk) (thunk)) values)

Composing the monadic value here is a good idea I think.

> +  ;; XXX: Non-local exits can leave PARAMETERS set to VALUES.
> +  (mlet* %store-monad ((old-values
> +                        (return (map set-value parameters values)))
> +                       (result (thunk)))
> +    (mbegin %store-monad
> +      (return (map set-value parameters old-values)) ;restore old values
> +      (return result))))

However, I'm not convinced it is meaningful to set the parameters for a
general monad, e.g. for the identity monad or the list monad, there is
no way for the parameters to have an effect, only during the evaluation
of a function. Instead, I would suggest to only do this for the state
monad, as the parameters have an effect during the function application
of the monadic value to the state. The same applies to `mparameterized'
in (guix monads). Do you think that makes sense?

This allows for the use of `with-fluids*', keeping the parameterization
local. In the following message is a patch with the changes, which
(apart from the issue below) appears to work.

When testing the patch however, I noticed that `with-fluids*' does not
work with prompts and I get the following error:

--8<---------------cut here---------------start------------->8---
ERROR: Wrong type (expecting resumable continuation): #<vm-continuation 7f595e325690>
--8<---------------cut here---------------end--------------->8---

Attached is a minimal example, which works fine if `with-fluids*' is
removed. Is this behavior expected (I didn't see it in the
documentation) or is it a bug in Guile?

Cheers,
David

(define p (make-parameter 1))

(define cont
  (call-with-prompt 'foo
	(lambda ()
	  (with-fluids* (list (parameter-fluid p))
		(list 2)
		(lambda ()
		  (+ (abort-to-prompt 'foo) (p)))))
	(lambda (k)
	  k)))

(p 3)

(pk (cont 0))