I think this is an interesting problem, so here are some additional
brainstorms on the issue that may or may not be useful...
One strategy to create a global mutable variable from inside the function
would be to use def at macroexpansion time to create a var, and then just
refer to it in the expansion, like this:
(defmacro expand-to-something-with-mutable-global []
; At macroexpansion time, create a (private) var containing a volatile.
(let [global-name (gensym "cache")]
(eval `(def ^:private ~global-name (volatile! nil)))
; Now macro can refer to this var, can use as a cache, etc.
`(if-let [cache-contents# (deref ~global-name)]
(do-something-with cache-contents#)
(reset! ~global-name init-value-for-cache))))
Not sure if this would be any faster than ConcurrentHashMap, but I would
guess that it would be if Clojure resolves the location of the var in
memory once, at compile-time.
A related technique would be for Specter to maintain an ArrayList of
volatiles. At macroexpansion time, you add a fresh volatile to the end of
the ArrayList, noting the index of its location, and then inside the macro
you hardcode a lookup in the ArrayList at the specific index to retrieve
the volatile containing the cache for this particular expansion. I would
expect this to be faster than looking up in a hash map, although there'd be
some additional concurrency/locking details to worry about that I assume
ConcurrentHashMap handles for you.
Or just use an ArrayList's slot directly as the cache (rather than storing
a volatile to add a level of indirection), but then the concurrency
logistics would be even more complicated.
On Tue, May 31, 2016 at 12:50 PM, Nathan Marz <[email protected]> wrote:
> No, because that global mutable variable would need to be specifiable by
> Specter on usage of the library. For example, if you wrote:
>
> (defn foo []
> (select [:a :b] {:a {:b 1}}))
>
> `select` has no ability to control anything outside the context of its
> form. It certainly can't wrap `foo` to put a volatile field in its closure.
> So for the static-field idea, it would expand to something like:
>
> (defn foo []
> (static-field [pathcache]
> (if-not pathcache (set! pathcache ...))
> ...
> ))
>
>
>
> On Tuesday, May 31, 2016 at 3:15:26 PM UTC-4, puzzler wrote:
>>
>> In your writeup, you say that there would be further speed benefits if
>> you could have a global mutable variable within the context of a function
>> (like a static field).
>>
>> Can't you effectively accomplish that already in Clojure like this?:
>>
>> (let [mycache (volatile! nil)]
>> (defn foo []
>> ...)))
>>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.