воскресенье, 15 октября 2017 г.

clojure debugging 2

(defmacro safe-eval
  "This macro is used to execute any function inside try-catch block.
  returns value or nil in case of Exception and prints debug info. "
  [& forms]
  `(try
     ~@forms
     (catch Exception e#
       (println "--------------")
       (println "file :" *file* \newline)
       (println "s-exp:" (quote ~@forms))
       (println "src  :" ~(meta &form))
       (println "=>" (.getMessage e#)))))

воскресенье, 8 октября 2017 г.

clojure debugging

Add to project.clj
;;scope capture for debugging
 [vvvvalvalval/scope-capture "0.1.0"]

(require 'sc.api)

(defn abc [x]
  (let [y (* 2 x)
        z (Math/pow x 4)]
    (sc.api/spy {:abc [x y z]})))

(abc 2)
;;prints during execution: SPY [1 -2]  where 1 is id for defsc

(sc.api/defsc 1)

;;show me the state of local vars from let using given id 4
(sc.api/letsc 4 [x y z])
;; recreate the last operation result from let using given id 2
(sc.api/letsc 2 {:abc [x y z]})

;;show me the info map at the spy execution point using id 2
(sc.api/ep-info 2)

see video: https://vimeo.com/237220354

воскресенье, 1 октября 2017 г.

network async communication

Nikita made a good library [net.async/async "0.1.0"] for asynchronous network communication.
https://github.com/tonsky/net.async


Just add this to your project.clj

      [org.clojure/clojure "1.8.0"]
      ;; async network communications
      [net.async/async "0.1.0" :exclusions [[org.clojure/clojure]
                                            [org.clojure/tools.logging]
                                            [org.clojure/core.async]]]

      [org.clojure/core.async "0.3.443" :exclusions [org.clojure/tools.reader]]

      [org.clojure/tools.logging "0.4.0"]

Here is an output of example below:
-------------------------------
server:  4263
client:  ECHO/4263
-------------------------------
server:  16640
client:  ECHO/16640
-------------------------------
server:  75968
client:  ECHO/75968
-------------------------------
server:  11092
client:  ECHO/11092
-------------------------------
server:  61707
client:  ECHO/61707
-------------------------------
server:  50773
client:  ECHO/50773
-------------------------------
server:  16803
client:  ECHO/16803
-------------------------------

Here is a source code of echo server and client:

(require '[clojure.core.async :refer [<! >!  <!! >!! close! go]])
(use 'net.async.tcp)

(def event-l-client (event-loop))
(def event-l-server (event-loop))

(defn echo-server [evt-loop]
  (let [acceptor (accept evt-loop {:port 8899})]
    (loop []
      (when-let [server (<!! (:accept-chan acceptor))]
        (go
          (loop []
            (when-let [msg (<! (:read-chan server))]
              (when-not (keyword? msg)
                (>! (:write-chan server) (.getBytes (str "ECHO/" (String. msg))))
                (println "server: " (String. msg)))
              (recur))))
        (recur)))))


(defn echo-client [evt-loop]
  (let [client (connect evt-loop {:host "127.0.0.1" :port 8899})]
    (loop []
      (go (>! (:write-chan client) (.getBytes (str (rand-int 100000)))))
      (loop []
        (let [read (<!! (:read-chan client))]
          (when (bytes? read) (println "client: " (String. read)))
          (when (and (keyword? read)
                     (not= :connected read))
            (println "disconnected from server. trying to reconnect using timeout")
            (recur))))
      (println "-------------------------------")
      (Thread/sleep (rand-int 3000))
      (recur))))


(future (echo-server event-l-server))

(future (echo-client event-l-client))

(shutdown! event-l-server)
(shutdown! event-l-client)