I'm trying to get println to output to an arbitrary location, either on the emacs-cider repl or to a JavaFX TextArea. I've referenced Why can't I print from background threads and this has allowed me to do println from within the JavaFX thread by rebinding *out* to that of the starting thread.
However this doesn't work when the println is called from a ChangeListener, whether created outside or inside the JFX thread.
In the text below I have two TextFields, one created in the main thread, one created in the JFX Thread, as well as two instances of ChangeListener, one as a defstruct which implements the interface, and another as a reify, both instantiated from within the JFX thread.
Each time I type a character in either of the two TextFields, the responding text shows up in the original thread's *out* stream.
How do I fix this so all printlns find the correct *out* as intended?
thanks
(ns junk.core
(:gen-class )
(:use jfxutils.core)
(:import (javafx.beans.value ObservableValue ChangeListener)
(javafx.stage Stage)
(javafx.scene Scene)
(javafx.scene.control TextArea TextField)
(javafx.scene.layout VBox)
(java.io PrintStream PrintWriter)))
(defn make-vbox-scene [& items]
(let [vb (VBox.)
scene (Scene. vb)]
(apply add-to-children vb items)
scene))
(defn make-window [scene & [width height]]
(let [stage (Stage.)]
(.setScene stage scene)
(when width (.setWidth stage width))
(when height (.setHeight stage height))
stage))
(defrecord myobservable []
ChangeListener
(^void changed [this ^ObservableValue obsval oldval newval]
;; This println goes to the original *out* stream
(println "Myobservable thread" (Thread/currentThread) ", *out* is " *out*)))
(def text1 (TextField. "hi")) ;; Created in main thread
(defn -start [myout]
;; Everything here is in JFX thread
(println "JFX thread is " (Thread/currentThread) ",JFX *out* is " *out*)
(binding [*out* myout] ;; only works for obvious/direct println, not from UI
(let [myobs (myobservable.) ;; Created in JFX thread
text2 (TextField. "bye") ;; Created in JFX thread
vbscene1 (make-vbox-scene text1 text2)
window1 (make-window vbscene1)]
;; This println works! Output goes to cider-repl or other PrintWriter pointed to by myout.
(println "After rebinding out, thread is " (Thread/currentThread) "*out* is " *out*)
;; These printlns go to the original *out* stream in the *nrepl-server junk* buffer, not cider
;; This means I also can't reassign the myout arg to some other PrintWriter
(-> text1 .textProperty (.addListener myobs))
(-> text1 .textProperty (.addListener (reify ChangeListener
(changed [this obsval oldval newval]
(println "Anonymous listener 1, thread is " (Thread/currentThread) "*out* is " *out*)))))
(-> text2 .textProperty (.addListener myobs))
(-> text2 .textProperty (.addListener (reify ChangeListener
(changed [this obsval oldval newval]
(println "Anonymous listener 2, thread is " (Thread/currentThread) "*out* is " *out*)))))
(.show window1))))
(defn main []
(println "main thread is " (Thread/currentThread) ", *out* is " *out*)
(run-now (-start *out*)))
(defn -main []
(javafx.application.Platform/setImplicitExit true) ;; Undoes false from jfxutils
(main))
Have you tried altering the var root of out? e.g.
(alter-var-root #'*out* (constantly *out*))
using binding will resolve the var to the bound value only for the current thread.
Other threads will continue to see the root value of the var, unless binding is used within those threads as well.
The callbacks (e.g. ChangeListener) are invoked from threads that are not under your control and therefore have no per-thread bindings. They will resolve the root value of the var.
You have to therefore alter the root value of out in order for those threads to resolve the value that you wish.
There is more information available on var bindings here.
Related
I want to figure out how best to create an async component, or accommodate async code in a Component-friendly way. This is the best I can come up with, and... it just doesn't feel quite right.
The Gist: take words, uppercase them and reverse them, finally print them.
Problem 1: I can't get the system to stop at the end. I expect to see a println of the individual c-chans stopping, but don't.
Problem 2: How do I properly inject deps. into the producer/consumer fns? I mean, they're not components, and I think they should not be components since they have no sensible lifecycle.
Problem 3: How do I idiomatically handle the async/pipeline-creating side-effects named a>b, and b>c? Should a pipeline be a component?
(ns pipelines.core
(:require [clojure.core.async :as async
:refer [go >! <! chan pipeline-blocking close!]]
[com.stuartsierra.component :as component]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PIPELINES
(defn a>b [a> b>]
(pipeline-blocking 4
b>
(map clojure.string/upper-case)
a>))
(defn b>c [b> c>]
(pipeline-blocking 4
c>
(map (comp (partial apply str)
reverse))
b>))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRODUCER / CONSUMER
(defn producer [a>]
(doseq [word ["apple" "banana" "carrot"]]
(go (>! a> word))))
(defn consumer [c>]
(go (while true
(println "Your Word Is: " (<! c>)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM
(defn pipeline-system [config-options]
(let [c-chan (reify component/Lifecycle
(start [this]
(println "starting chan: " this)
(chan 1))
(stop [this]
(println "stopping chan: " this)
(close! this)))]
(-> (component/system-map
:a> c-chan
:b> c-chan
:c> c-chan)
(component/using {}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; RUN IT!
(def system (atom nil))
(let [_ (reset! system (component/start (pipeline-system {})))
_ (a>b (:a> #system) (:b> #system))
_ (b>c (:b> #system) (:c> #system))
_ (producer (:a> #system))
_ (consumer (:c> #system))
_ (component/stop #system)])
EDIT:
I started thinking about the following, but I'm not quite sure if it's closing properly...
(extend-protocol component/Lifecycle
clojure.core.async.impl.channels.ManyToManyChannel
(start [this]
this)
(stop [this]
(close! this)))
I rewrote your example a little to make it reloadable:
Reloadable Pipeline
(ns pipeline
(:require [clojure.core.async :as ca :refer [>! <!]]
[clojure.string :as s]))
(defn upverse [from to]
(ca/pipeline-blocking 4
to
(map (comp s/upper-case
s/reverse))
from))
(defn produce [ch xs]
(doseq [word xs]
(ca/go (>! ch word))))
(defn consume [ch]
(ca/go-loop []
(when-let [word (<! ch)]
(println "your word is:" word)
(recur))))
(defn start-engine []
(let [[from to] [(ca/chan) (ca/chan)]]
(upverse to from)
(consume from)
{:stop (fn []
(ca/close! to)
(ca/close! from)
(println "engine is stopped"))
:process (partial produce to)}))
this way you can just do (start-engine) and use it to process word sequences:
REPL time
boot.user=> (require '[pipeline])
boot.user=> (def engine (pipeline/start-engine))
#'boot.user/engine
running with it
boot.user=> ((engine :process) ["apple" "banana" "carrot"])
your word is: TORRAC
your word is: ANANAB
your word is: ELPPA
boot.user=> ((engine :process) ["do" "what" "makes" "sense"])
your word is: OD
your word is: SEKAM
your word is: ESNES
your word is: TAHW
stopping it
boot.user=> ((:stop engine))
engine is stopped
;; engine would not process anymore
boot.user=> ((engine :process) ["apple" "banana" "carrot"])
nil
State Management
Depending on how you intend to use this pipeline, a state management framework like Component might not be needed at all: no need to add anything "just in case", starting and stopping the pipeline in this case is a matter of calling two functions.
However in case this pipeline is used within a larger app with more states you could definitely benefit from a state management library.
I am not a fan of Component primarily because it requires a full app buyin (which makes it a framework), but I do respect other people using it.
mount
I would recommend to either not use anything specific in case the app is small: you, for example could compose this pipeline with other pipelines / logic and kick it off from -main, but if the app is any bigger and has more unrelated states, here is all you need to do to add mount to it:
(defstate engine :start (start-engine)
:stop ((:stop engine)))
starting pipeline
boot.user=> (mount/start)
{:started ["#'pipeline/engine"]}
running with it
boot.user=> ((engine :process) ["do" "what" "makes" "sense"])
your word is: OD
your word is: SEKAM
your word is: ESNES
your word is: TAHW
stopping it
boot.user=> (mount/stop)
engine is stopped
{:stopped ["#'pipeline/engine"]}
Here is a gist with a full example that includes build.boot.
You can just download and play with it via boot repl
[EDIT]: to answer the comments
In case you are already hooked on Component, this should get you started:
(defrecord WordEngine []
component/Lifecycle
(start [component]
(merge component (start-engine)))
(stop [component]
((:stop component))
(assoc component :process nil :stop nil)))
This, on start, would create a WordEngine object that would have a :process method.
You won't be able to call it as you would a normal Clojure function: i.e. from REPL or any namespace just by :requireing it, unless you pass a reference to the whole system around which is not recommended.
So in order to call it, this WordEngine would need to be plugged into a Component system, and injected into yet another Component which can then destructure the :process function and call it.
I am looking for a way to determine if a function printed (using println or anything similar).
What I am trying to determine is if test-vars printed something or not.
The issue with this function is that it doesn't return anything, but only print things when errors got issues, but I want to know if it succeeded or not and the only way I see to know it is to check if it printed something or not.
Even better would be a way to "intercept" what is going to out and to put it in a variable.
After the comments from #lee and #leetwinski I tried the following:
(deftest test-1
(testing
(is (= 1 2))))
Then I tried to run that test using:
(let [printed (with-out-str (test-vars [#'test-1]))]
(print (str "Printed size: " (count printed))))
But here is what I got:
FAIL in (test-1) (form-init505699766276988020.clj:103)
expected: (= 1 2)
actual: (not (= 1 2))
Printed size: 0
nil
So, what test-vars outputs has been outputted anyway. Then printed was empty.
in addition to #Lee's answer: in general you could just rebind *out* to any other writer you want:
temporary binding:
user> (binding [*out* (java.io.StringWriter.)]
(println 101)
(str *out*))
"101\n"
is just an analogue to with-out-str
thread-local binding:
user> (set! *out* (java.io.StringWriter.))
#object[java.io.StringWriter 0x575e6773 ""]
user> (println 123)
nil
user> (str *out*)
"123\n"
here we rebind the *out*, for the current thread (and for all the threads, spawned from it, AFAIK).
You can use with-out-str which intercepts printed values and collects them into a string:
(let [printed (with-out-str (test-vars))]
...)
(deftask test1 "first test task" [] (print "1") identity)
(deftask test2 "second test task" [] (print "2") identity)
(boot (comp (test1) (test2)))
=> 12nil
(boot (comp (fn [x] (print "1") identity) (fn [x] (print "2") identity)))
=> 21nil
If I use comp on tasks, the execution order is from left to right. If I use comp on anonymous functions, the execution order is from right to left. How is this inconsistency reasonable?
The reason for that difference is that when you use comp with boot tasks is that they are not bare logic that gets composed but each boot tasks returns a function which will be invoked later and that function wraps another function which is passed to it (like in ring middleware).
With plain functions it works like this:
(comp inc dec)
produces a function which does following:
(inc (dec n))
In boot tasks are similar to ring middleware. Each task is a function which returns another function that will wrap the next handler from the pipeline. It works like that (not literally, it's simplified for readability sake):
(defn task1 []
(fn [next-handler]
(fn [fileset]
(print 1) ;; do something in task1
(next-handler fileset))) ;; and call wrapped handler
(defn task2 []
(fn [next-handler]
(fn [fileset]
(print 2) ;; do something in task1
(next-handler fileset)))) ;; and call wrapped handler
So when you do:
(comp (task1) (task2))
And execute such composed task it works as if it was:
(fn [fileset1]
(print 1)
((fn [fileset2]
(print 2)
(next-handler fileset2))
fileset1))
Because a function produces by (task2) will be passed to function produced by (task1) which will wrap the one from (task2) (and call it after printing 1).
You can read more on boot tasks anatomy in its wiki. It might be also useful to read on ring middleware.
I'm writing a small tool in clojure and want to know when there's been a change on the clipboard. Here's a simplified version of what's going on.
(:import java.awt.Toolkit)
(:import (java.awt.datatransfer Clipboard
ClipboardOwner
Transferable
StringSelection
DataFlavor
FlavorListener))
(defn get-clipboard [] (. (Toolkit/getDefaultToolkit)
(getSystemClipboard)))
(defn get-content []
(.getContents (get-clipboard) nil))
(def content (agent (get-content)))
(defn watch [key f]
(add-watch content key f))
(defn -main []
(while (not= content "banana-man")
(watch :watcher
(fn [key agent old-state new-state]
(prn "-- agent Changed --")
(prn "key" key)
(prn "atom" agent)
(prn "old-state" old-state)
(prn "new-state" new-state)))))
I've added in a while loop just to keep the main function from shutting down immediately.
This runs without throwing any errors, but does not report when changes have been made on the clipboard or stop the while loop when I copy bannan-man to the clipboard. I've been struggling with this for a few weeks now and I'm sure I'm missing something simple. If anyone has some advice I would really appreciate it!
For starters, content is an agent, so it will never be equal to a string. You should deref the agent using # in order to make that comparison.
The while loop is not needed to prevent exit. If you use the agent thread pool, Clojure will not shut down until you explicitly run shutdown-agents. But we will need it to manage your agent updates.
content is not going to change after your initial assignment unless you explicitly send it an updating function with send or send-off. Don't let the name mislead you, agents are not autonomous, and are not scheduled or repeated tasks. Try something like this:
(defn -main []
(watch :watcher
(fn [key agent old-state new-state]
(prn "-- agent Changed --")
(prn "key" key)
(prn "atom" agent)
(prn "old-state" old-state)
(prn "new-state" new-state)))
(while (not= #content "banana-man")
(send-off content (fn [& _] (get-content)))
(Thread/sleep 250))
(shutdown-agents))
While preparing an answer to another question, I created one for myself. Consider the following short program.
(ns net.dneclark.JFrameAndTimerDemo
(:import (javax.swing JLabel JButton JPanel JFrame Timer))
(:gen-class))
(defn timer-action [label counter]
(proxy [java.awt.event.ActionListener] []
(actionPerformed
[e]
(.setText label (str "Counter: " (swap! counter inc))))))
(defn timer-fn []
(let [counter (atom 0)
label (JLabel. "Counter: 0")
timer (Timer. 1000 (timer-action label counter))
panel (doto (JPanel.)
(.add label))]
(.start timer)
(doto (JFrame. "Timer App")
(.setContentPane panel)
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setLocation 300 300)
(.setSize 200 200)
(.setVisible true))))
(defn -main []
(timer-fn))
In the action listener, 'timer-action', the value of the 'counter' argument is altered. The actual variable is declared in the 'timer-fn' function, but is altered in the listener. In my earlier experience with languages like Pascal, I would have considered 'counter' to be passed by reference. Is that the case here or is this an example of a closure? Something else?
Thanks for the help.
Yes, it's a closure. The lexical context of the handler function definition is preserved, and when it is later invoked it can access and update variables that "live" there.
I'm not sure how to answer the question, "why?" other than to point out that it's simply the way the language is defined to work.