On Sat, Nov 27, 2010 at 9:19 PM, Ken Wesson <kwess...@gmail.com> wrote:
> On Sat, Nov 27, 2010 at 7:50 PM, Mike Meyer
> <mwm-keyword-googlegroups.620...@mired.org> wrote:
>> My simple web app
>> (http://blog.mired.org/2010/11/x10-controller-in-clojure.html) has
>> some stuff that needs to happen just once (in this case, opening the
>> serial port). It's not clear how to get this to happen using ring. If
>> I do it inside my ring handler, then it gets run on every request, and
>> I have to check to make sure it's not run multiple times. If I run it
>> outside the handler, then it gets run when I do "lein uberwar", which
>> is simply wrong.
>>
>> When the deployment platform activates the war would seem to be the
>> right time to run this ("war load time"?). So maybe this is a question
>> that depends on the deployment platform, or war? However, a quick
>> google search didn't turn up anything that looked interesting.
>>
>> Anyone got suggestions on how to set up code to be run when Jetty (or
>> tomcat, or ...)?
>
> If it were an ordinary application, -main would be the obvious place
> (or some module-init function eventually called from there). In this
> case, though, I think your best bet may actually be a Java
> lazily-initialized singleton that you access from Clojure, if
> performance is an issue, or else the Clojure equivalent:
>
> (defmacro defsingleton [name init-sexp]
>  `(def ~name
>     (let [singleton-uninitialized# (Object.)
>           a# (atom singleton-uninitialized#)]
>       (fn []
>         (let [x# @a#]
>           (if (= x# singleton-uninitialized#)
>             (do
>               (reset! a# ~init-sexp)
>               @a#)
>             x#))))))
>
> user=> (defsingleton foo (do (println "foo initialized") 7))
> #'user/foo
> user=> (foo)
> foo initialized
> 7
> user=> (foo)
> 7
>
> You can also abuse futures:
>
> user=> (def foo (future (do (println "foo initialized") 7)))
> #'user/foo
> user=> @foo
> foo initialized
> 7
> user=> @foo
> 7
>
> or delay/force, or even lazy-seq:
>
> user=> (def foo (drop 1 (take 2 (iterate (fn [_] (do (println "foo
> initialized") 7)) nil))))
> #'user/foo
> user=> (first foo)
> foo initialized
> 7
> user=> (first foo)
> 7

Or memoize:

user=> (defn foo [] (do (println "foo initialized") 7))
#'user/foo
user=> (def foo (memoize foo))
#'user/foo
user=> (foo)
foo initialized
7
user=> (foo)
7

which actually is fairly close to what the defsingleton macro does.

-- 
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

Reply via email to