From kilian.sprotte at gmail.com Sun Dec 1 09:58:45 2013 From: kilian.sprotte at gmail.com (Kilian Sprotte) Date: Sun, 1 Dec 2013 09:58:45 +0000 (UTC) Subject: [closer-devel] WITH-ACTIVE-LAYERS does not eval its args. Alternatives? Message-ID: Hi, I have run into a situation, where I would want WITH-ACTIVE-LAYERS to evaluate its layer arguments or to have an alternative construct which does so. My questions are: 1. Is there a reason for WITH-ACTIVE-LAYERS to be designed this way? 2. Is there an alternative that allows me to achieve the desired effect? ENSURE-ACTIVE-LAYER and ENSURE-INACTIVE-LAYER being functions of course evaluate their arguments, but using them together with an UNWIND-PROTECT does not work, because ENSURE-ACTIVE-LAYER works globally and also affects other threads. The background is that I am using layers to represent different backends in a database API. I would need WITH-ACTIVE-LAYERS to evaluate its argument in the following example: A user wants to connect to the database, so he specifies some connection settings, including the backend to be used: (defun open-db (spec) (destructuring-bind (backend &rest args) spec (with-active-layers (backend) (apply #'%open-db args)))) Suggestions or Remarks? Thanks Kilian From pc at p-cos.net Sun Dec 1 17:28:38 2013 From: pc at p-cos.net (Pascal Costanza) Date: Sun, 1 Dec 2013 18:28:38 +0100 Subject: [closer-devel] WITH-ACTIVE-LAYERS does not eval its args. Alternatives? In-Reply-To: <72590347-4A14-42F5-B327-64AE2CD46442@p-cos.net> References: <72590347-4A14-42F5-B327-64AE2CD46442@p-cos.net> Message-ID: <15468C82-F9D3-4C9F-8CF7-B1BAACC255D5@p-cos.net> On 1 Dec 2013, at 13:56, Pascal Costanza wrote: > Hi Kilian, > > On 1 Dec 2013, at 10:58, Kilian Sprotte wrote: > >> Hi, >> >> I have run into a situation, where I would want WITH-ACTIVE-LAYERS to >> evaluate its layer arguments or to have an alternative construct which >> does so. >> >> My questions are: >> >> 1. Is there a reason for WITH-ACTIVE-LAYERS to be designed this way? > > Yes, the macro version can be implemented more efficiently, because you already know at macro-expansion time what layers to activate. > >> 2. Is there an alternative that allows me to achieve the desired >> effect? > > Yes. adjoin-layer and remove-layer allow you to programmatically create new combinations of layers. You need to pass one layer and a ?layer context?, which is an already composed set of layers. You need to call adjoin-layer and remove-layer several times if you want to compose several layers, because composition ordering matters. current-layer-context gives you a context of the currently active layers. So adjoin-layer, remove-layer, and current-layer-context in combination are the functions to compute new sets of layers. > > Once you have a new layer context, you can use funcall-with-layer-context or apply-with-layer-context to execute a block of code within that context. > > Such contexts are first-class, so you can store them and pass them around. A bit more detail: For example, you can also do something like this. (defvar *some-context* (with-active-layers (l1 l2 l3) (current-layer-context))) ?and then later? (funcall-with-layer-context *some-context* (lambda () (do-this) (do-that))) Pascal -- Pascal Costanza From pc at p-cos.net Sun Dec 1 12:56:22 2013 From: pc at p-cos.net (Pascal Costanza) Date: Sun, 1 Dec 2013 13:56:22 +0100 Subject: [closer-devel] WITH-ACTIVE-LAYERS does not eval its args. Alternatives? In-Reply-To: References: Message-ID: <72590347-4A14-42F5-B327-64AE2CD46442@p-cos.net> Hi Kilian, On 1 Dec 2013, at 10:58, Kilian Sprotte wrote: > Hi, > > I have run into a situation, where I would want WITH-ACTIVE-LAYERS to > evaluate its layer arguments or to have an alternative construct which > does so. > > My questions are: > > 1. Is there a reason for WITH-ACTIVE-LAYERS to be designed this way? Yes, the macro version can be implemented more efficiently, because you already know at macro-expansion time what layers to activate. > 2. Is there an alternative that allows me to achieve the desired > effect? Yes. adjoin-layer and remove-layer allow you to programmatically create new combinations of layers. You need to pass one layer and a ?layer context?, which is an already composed set of layers. You need to call adjoin-layer and remove-layer several times if you want to compose several layers, because composition ordering matters. current-layer-context gives you a context of the currently active layers. So adjoin-layer, remove-layer, and current-layer-context in combination are the functions to compute new sets of layers. Once you have a new layer context, you can use funcall-with-layer-context or apply-with-layer-context to execute a block of code within that context. Such contexts are first-class, so you can store them and pass them around. > The background is that I am using layers to represent different > backends in a database API. I would need WITH-ACTIVE-LAYERS to > evaluate its argument in the following example: A user wants to > connect to the database, so he specifies some connection settings, > including the backend to be used: > > (defun open-db (spec) > (destructuring-bind (backend &rest args) spec > (with-active-layers (backend) > (apply #'%open-db args)))) > > Suggestions or Remarks? This is exactly the kind of case for which the first-class contexts are designed, and I have used them in similar situations for some demos. Please let me know if you run into any problems with this. I hope this helps, Pascal -- Pascal Costanza