Hi :) On Sun 24 Nov 2019 18:54, Ludovic Courtès <l...@gnu.org> writes:
> It seems that if you ‘set!’ a public variable of a declarative module, > the change is visible to all the module users, but it’s not necessarily > visible to procedures within that module, presumably because they use an > inlined or specialized variant of that thing. > > I would have imagined that public bindings are considered mutable and > thus not subject to inlining; OTOH, that would obviously be a loss, so > the current approach makes sense. Right, I understand the frustration. For what it is worth, I think we have the right default for what it means to be a declarative module, but I'm definitely open to having that conversation. > Anyway, it complicates a use case for me. In Guix, we “mock” bindings > like so: > > (define-syntax-rule (mock (module proc replacement) body ...) > "Within BODY, replace the definition of PROC from MODULE with the > definition > given by REPLACEMENT." > (let* ((m (resolve-interface 'module)) > (original (module-ref m 'proc))) > (dynamic-wind > (lambda () (module-set! m 'proc replacement)) > (lambda () body ...) > (lambda () (module-set! m 'proc original))))) > > and that allows us to write tests that temporarily modify public (or > private!) bindings. > > It seems like this could be addressed by compiling selected modules with > ‘user-modules-declarative?’ set to #false, or by avoiding the above hack > altogether when possible, but I thought I’d share my impressions and > listen to what people think. :-) This works. (Actually the way I would do it is to pass #:declarative? #f in the define-module for the modules in question.) Marking some bindings as not declarative also works (e.g. (set! foo foo)). For me the most robust solution would be to have `mock' verify that the module it's funging isn't declarative. We don't currently have a way to know if an individual module binding is declarative or not (though we could add this). Cheers, Andy