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 <nathan.m...@gmail.com> 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 clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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 clojure+unsubscr...@googlegroups.com.
> 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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to