archimag / restas

Common Lisp web framework
http://restas.lisper.ru/
Other
257 stars 50 forks source link

Request: context-dependent functions #17

Open necto opened 11 years ago

necto commented 11 years ago

It would be nice to have a macros (e. g. cdefun) like define-route, but defining a generic function, which takes an additional argument - the submodule-designated symbol. Each mount-submodule also generate methods for those function, specialized for the symbol, specified in it. Those methods will just put the code of the function into the submodule context, with all dynamically scoped variables will seem like the function is called from a route of this submodule. For example:

; mod1:

(defvar *var* 0)
(cdefun add-var (a) (+ *var* x) ) ; <-- the function here depend on dynamically scoped context

; mod2:

(mount-submodule sm1 (#:mod1) ; <-- Create two different contexts
   (mod1:*var* 1))                         ;     /
(mount-submodule sm2 (#:mod1) ; <-
   (mod1:*var* 2))

; Call function in different contexts
(mod1:add-var 'sm1 1) ;--> 2
(mod1:add-var 'sm2 1) ;--> 3

;mod3:

(mount-submodule sm1 (#:mod1)
  (mod1:*var* 41))

(mod1:add-var 'sm1 1) ;--> 42

Here the first invocation and the third will refer to the different methods, because the symbols mod2:sm1 and mos3:sm1 are different.

I know one way to achieve such results now -- using the restas:with-context macro. But it is quite verbose (and undocumented, as far as I know):

(restas:with-context (second (gethash 'sm1 *submodules*))
   (mod1:add-var 1))

And it still handles restas:genurl improperly (relative to the current module, not to the 'sm1). It's just a proposal, may be there is a more elegant solution.

tmccombs commented 10 years ago

Commit f259aea700a94b7365d3f6ed6e99619be44331df partially solves this problem. You can now replace your with-context hack with

(restas:with-module 'sm1
  (mod1:add-var 1))

With this it would be straightforward to implement the cdefun macro you mention.