【问题标题】:Redirecting clojure's *out* to a core.async channel将 clojure 的 *out* 重定向到 core.async 通道
【发布时间】:2014-09-28 13:15:17
【问题描述】:

我正在尝试让 clojure 程序中的所有打印语句将它们的字符串放在 core.async 通道上。有什么办法可以做到吗?

(我正在尝试让 cljsbuild 将其编译器消息发送到前端。)

【问题讨论】:

    标签: clojure core.async


    【解决方案1】:
    (def is (java.io.PipedInputStream.))
    (def os (java.io.PipedOutputStream. is))
    
    (def channel (chan))
    
    (.start (Thread. (fn []
                       (let [buffer (byte-array 1024)]
                         (while true
                           (let [n (.read is buffer 0 1024)]
                             (>!! channel (vec (take n buffer)))))))))
    
    (binding [*out* (java.io.OutputStreamWriter. os)]
      (println "Hello, world!"))
    

    【讨论】:

      【解决方案2】:

      gfredericks 在#clojure irc 中给了我这个参考。他建议我调整 nREPL 的做法:

      (defn- session-out
        "Returns a PrintWriter suitable for binding as *out* or *err*.  All of
         the content written to that PrintWriter will (when .flush-ed) be sent on the
         given transport in messages specifying the given session-id.
         `channel-type` should be :out or :err, as appropriate."
        [channel-type session-id transport]
        (let [buf (clojure.tools.nrepl.StdOutBuffer.)]
          (PrintWriter. (proxy [Writer] []
                          (close [] (.flush ^Writer this))
                          (write [& [x ^Integer off ^Integer len]]
                            (locking buf
                              (cond
                                (number? x) (.append buf (char x))
                                (not off) (.append buf x)
                                ; the CharSequence overload of append takes an *end* idx, not length!
                                (instance? CharSequence x) (.append buf ^CharSequence x (int off) (int (+ len off)))
                                :else (.append buf ^chars x off len))
                              (when (<= *out-limit* (.length buf))
                                (.flush ^Writer this))))
                          (flush []
                            (let [text (locking buf (let [text (str buf)]
                                                      (.setLength buf 0)
                                                      text))]
                              (when (pos? (count text))
                                (t/send (or (:transport *msg*) transport)
                                        (response-for *msg* :session session-id
                                                      channel-type text))))))
                        true)))
      

      来自nREPL source here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-11
        • 2015-07-04
        • 2014-03-20
        • 2019-02-13
        • 1970-01-01
        • 2015-05-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多