5 ms·
Clojure has all sorts of facilities to do that (atoms, agents or refs). You can even listen for changes [1] and compare old and new values. [1] https://clojure
by dig1 6y ago
Clojure has all sorts of facilities to do that (atoms, agents or refs). You can even listen for changes [1] and compare old and new values.
[1] https://clojuredocs.org/clojure.core/add-watch https://clojuredocs.org/clojure.core/add-watch
- bjourne 6y agoInteresting, I didn't know that. I don't understand how the function you link to can be used to accomplish that. Can you give me an example?
- dig1 6y agoSure; here is example with atom: ;; define a map (def myvar (atom {:foo 1})) ;; add watcher for 'myvar'; it will call anonymous ;; function and set old-state with previous value and new-state ;; with new value, when 'myvar' was changed (add-watch myvar :dummy (fn [_ _ old-state new-state] (println "changed! - old: " old-state " new: " new-state))) ;; Run separate thread and and update :foo value to 2, after 6 seconds. ;; No scheduling is necessary, this is so it can be evaluated in REPL easily. (future (Thread/sleep 6000) (swap! myvar assoc :foo 2)) ;; Infinite loop. Sleep for 0.5 seconds just for printing purposes. (loop [] (println @myvar) (Thread/sleep 500) (recur)) and you will see output like this: {:foo 1} {:foo 1} {:foo 1} {:foo 1} {:foo 1} {:foo 1} {:foo 1} {:foo 1} changed! - old: {:foo 1} new: {:foo 2} {:foo 2} {:foo 2} {:foo 2} {:foo 2} {:foo 2} {:foo 2}
- bjourne 6y agoThat is an example of thread messaging - not hot-swapping. Had myvar been local to the thread it wouldn't have worked.
- dig1 6y agoI used different thread just for printing/add-watch purposes. But, using myvar or your-like example (hot loading function) in the same thread works without any problems as well - put function in a loop, change function body and reload namespace where myvar/function exists - loop will pick that up instantly.
- bjourne 6y agoIn your example, you modified the assoc while another thread was accessing it. That is a standard feature of languages with threading support and is not impressive. Let me give you a clearer example than my first one: def fn(): d = {'name' : 'hello'} while True: print(d['name']) threading.Thread(target=fn).run() This causes a thread to be started which prints "hello" indefinitely. Clojure cannot, while the thread is running, change the execution to, say: def fn(): d = {'name' : 'there'} while True: print(d['name']) time.sleep(0.5) Clojure cannot change the value of the local variable d because it has no reference to it. Clojure cannot add the line time.sleep(0.5) to the loop because it has no facility for "upgrading" running threads.
- dig1 6y agoCheck [1] to see what I'm talking about. I'd suggest you to investigate more before making such bold claims. [1] http://webcache.googleusercontent.com/search?q=cache:ieBuArSKu2MJ:travis-whitton.blogspot.com/2009/09/hot-code-swapping-with-clojure.html+&cd=3&hl=en&ct=clnk&gl=ba http://webcache.googleusercontent.com/search?q=cache:ieBuArS...
- bjourne 6y agoYou are quite arrogant. He reloads and rebinds functions and symbols. That is not the same thing as hot-swapping functions. Hot-swapping means that the function is running and in his example no running function is replaced. Had the main function looked like this: (defn main [] (let [what "blah"] (loop [] (println what) (Thread/sleep 1000) (recur)))) It would neither have been possible to change the output nor the sleep time.
- deleted 6y ago[deleted]