From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Amirouche Boubekki Newsgroups: gmane.lisp.guile.devel Subject: Re: Mutating public bindings of a declarative module Date: Mon, 25 Nov 2019 07:23:37 +0100 Message-ID: References: <87a78lyxbi.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="133265"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Andy Wingo , Guile Devel To: =?UTF-8?Q?Ludovic_Court=C3=A8s?= Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Mon Nov 25 07:24:00 2019 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iZ7mx-000YSE-QL for guile-devel@m.gmane.org; Mon, 25 Nov 2019 07:23:59 +0100 Original-Received: from localhost ([::1]:40622 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZ7mw-0001Gd-MZ for guile-devel@m.gmane.org; Mon, 25 Nov 2019 01:23:58 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:38201) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZ7mr-0001Ea-LB for guile-devel@gnu.org; Mon, 25 Nov 2019 01:23:54 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iZ7mq-0004f9-A6 for guile-devel@gnu.org; Mon, 25 Nov 2019 01:23:53 -0500 Original-Received: from mail-vs1-xe42.google.com ([2607:f8b0:4864:20::e42]:37242) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iZ7mo-0004cX-AX; Mon, 25 Nov 2019 01:23:50 -0500 Original-Received: by mail-vs1-xe42.google.com with SMTP id u6so9280456vsp.4; Sun, 24 Nov 2019 22:23:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=aufiPgmuyNCURqIw6QwYK1XPUiw8r8ESnZwmX5LiGpU=; b=aAh/BWPsLCjQ2UTnjq17lYbYEpUY7CIk58cpN90ZNZNup4zcJM/4Edkqb4605luPJ0 d0gm7/qGTGOyCmPUndY0zn7z8kg7Ld73ZXGJb/qs3PfanLWZ3saskCT97WXNpcajxnzU /owGDjx2yprO2MqA81jSOlxtOy5fhpxYIVD31/lGSKgTVHEa3Hs60dfFwIboz17r4QAQ 44xEjouQhxmcZTv0rSGaefuwuovSsmds8ScWeqiX2Bps3aP+S4s14AWgj+us/flwsZyV eKBMfbtY7EiEykyY2OKsGJvsp6tADC/OT7bGuhj9lLE7Ml5GI0C1rFY0dKsNNFVkKtjG SzNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=aufiPgmuyNCURqIw6QwYK1XPUiw8r8ESnZwmX5LiGpU=; b=eoUmZWV+bgCA68I/kQmbu5ErbNw1wGNYynzVsGpMQJg6KGYrqUoLF+9IA5W0n432Og rnzMB79e/SF2kP+/iVFu8EQo/kFVcH12yD47RdSDfiwDb+WDi+J1aPbOgOcp2NU1CSlC cL1puOL/PVfGB+jq3yu1wI00Ah8mnolm1gdozNiG53ixjjYY+i4dEwCieRyWxwuvUpIa 07JV/yct6Ca9DNlv5S08qPI8WL6+o7XIBWrLwNXVET98h3R/beUvDM7w+CiTA0KxnJhW F8l3SbV//5PjCkBz8O9jODBEIYRMBG7lew9dy79veKKkd5Oy84Ykf3hV86Qy//Ka6X8N UIbw== X-Gm-Message-State: APjAAAWAfFcK98mlayZMk301ZE9DMjxX8QOMbfYTNAmxSxg2lZuKA8Qb 8pzyB8RvosNvXoxmAm7XnEdBraNA3F3jJngnnENrM9xN X-Google-Smtp-Source: APXvYqzy4Sl0wZbEQ/mmgHLEIlHOP2mmjG03no62PG4UIL5XkhexqsCUaAjhNUNAiw/4tvBYgL1Y2zunfnXjICh6XjQ= X-Received: by 2002:a67:bd05:: with SMTP id y5mr17893658vsq.180.1574663028298; Sun, 24 Nov 2019 22:23:48 -0800 (PST) In-Reply-To: <87a78lyxbi.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::e42 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.org gmane.lisp.guile.devel:20160 Archived-At: Le dim. 24 nov. 2019 =C3=A0 18:54, Ludovic Court=C3=A8s a = =C3=A9crit : > > Hello! > > It seems that if you =E2=80=98set!=E2=80=99 a public variable of a declar= ative module, > the change is visible to all the module users, but it=E2=80=99s not neces= sarily > 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. > > Anyway, it complicates a use case for me. In Guix, we =E2=80=9Cmock=E2= =80=9D bindings > like so: > > (define-syntax-rule (mock (module proc replacement) body ...) > "Within BODY, replace the definition of PROC from MODULE with the def= inition > 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 > =E2=80=98user-modules-declarative?=E2=80=99 set to #false, or by avoiding= the above hack > altogether when possible, but I thought I=E2=80=99d share my impressions = and > listen to what people think. :-) > For what it is worth, in my project I take a different approach to mock. Some may call it inversion-of-control of something like that. Basically, everything that must be mocked is passed as a procedure. For instance, in babelia there is a pool of thread worker with a fibers mainthread. There is three primitives: initialize the thread pool, apply a thunk in a worker, and for-each-par-map. During the tests I can not run the pool of thread worker because of the #:drain behavior [0], I could workaround it some other way like explained in the ticket by Wingo. [0] https://github.com/wingo/fibers/issues/30 Anyway, the other advantage of making the thread pool configurable is that my OKVS abstraction is not tied to it. The full-text search abstraction dubbed fts is passed `apply` and `for-each-map` as last two arguments in the constructor: (define-record-type (make-fts engine ustore prefix limit apply for-each-map) fts? (engine fts-engine) (prefix fts-prefix) (ustore fts-ustore) (limit fts-limit) (apply %fts-apply) (for-each-map %fts-for-each-map)) Then during the tests or else, I can pass custom implementations: (define (for-each-map sproc pproc lst) (for-each sproc (map pproc lst))) (define fts (make-fts engine ustore '(test-fts-prefix) 1 (lambda (thunk) (apply thunk '())) ;; fts-apply for-each-map)) Similarly, in OKVS SRFI, see [1], to make database engine swappable, I rely on a similar pattern that was dubbed typeclass object by SRFI-128 (comparators). In those cases, the record instance contains only procedures. [1] https://github.com/scheme-requests-for-implementation/srfi-167/blob/mas= ter/srfi/engine.sld#L1 The approach I described, that boils down to passing a wanna be mocked procedure as argument, can work. > Thanks, > Ludo=E2=80=99. Hope this helps.