Fork me on GitHub
#clojure
<
2019-08-06
>
borkdude08:08:03

I want to make a reader function for a tag like this: #jet/val "/"

borkdude08:08:27

and I've defined this in src/data_readers.clj: {jet/val clojure.core/str #_jet.data-readers/val}

borkdude08:08:45

but I'm getting:

$ echo '{:a "foo bar" :b 2}' | lein jet --from edn --to edn --query "(str :a #jet/val "/" :b)"
Exception in thread "main" java.lang.RuntimeException: No reader function for tag jet/val

borkdude08:08:41

got it, it's an edn/read-string option

borkdude09:08:42

I guess not, but are there also data readers that can read multiple forms, not only the one following it?

dominicm09:08:35

Nope, only one. Wrap in a vector to read "multiple"

borkdude09:08:32

I was trying to avoid wrapping in a vector 🙂

borkdude09:08:44

For cmd line usage it may be handy to do something like:

jet ... --query '
#jet/do :a
#jet/do :b
'
instead of writing:
jet ... --query '[
:a
:b
] ;; <- user might forget to close this
'

borkdude09:08:28

but that's mostly a gimmick, I will admit

borkdude09:08:52

I could wrap the entire query in an implicit vector

dominicm09:08:31

well, in the former case you can repeatedly read until you get eof

dominicm09:08:39

that is, clojure.edn/read

borkdude09:08:57

yeah, or just wrap a vector and then read, a common trick

borkdude09:08:11

the vector already means a sequential query, so like implicit do, I might just wrap it

vinurs15:08:31

hello, how can i convert this java to clojure, in clojure i use ring, so i don’t have httpservletrequest,

vinurs15:08:41

in ring params i print is #object[java.io.ByteArrayInputStream 0x6b7b093d [email protected]]

lukasz15:08:50

(slurp ( (.getInputStream request))) should work

lukasz15:08:30

worth checking out included/missing ring middlewares, as they should handle converting params, request body etc into clojure maps

vinurs15:08:35

i have no request variable, in clojure ring is there HttpServletRequest?

lukasz15:08:06

AFAIR it's in :body or :params keys of the request map

vinurs15:08:24

yes, i found it in :body

lukasz15:08:36

this should help

vinurs15:08:24

i need to call the service.verify(params) function, its params is a java map

vinurs15:08:05

i don’t know here which i can use as the param for verify

lukasz16:08:54

@haiyuan.vinurs how is the data sent to your web service? POST? query params?

dangercoder18:08:47

How do you guys handle contextual logging when using e.g manifold or core-async?

noisesmith18:08:39

@jarvinenemil just a theory: you could use binding to set contextual values for a specific call, and refer to the bound value in your logs

noisesmith18:08:21

rough sketch:

(def ^:dynamic *user*)
(def ^:dynamic *task*)

(defn foo [uname]
 (binding [*user* uname
          *task* "foo"]
     (bar uname))

dangercoder18:08:37

ah ok, I've never really done "contextual logging" in Clojure before so it would be interesting to know how people do it when it comes to async-stuff. In Java I've always just set the MDC (thread local). Let's say you have a system with bank transactions and you want to have a trace-id for the transaction in the whole system.

noisesmith18:08:54

async stuff respects dynamic bindings

😱 4
souenzzo21:08:47

there is docs about it? Something explaning how clojure do that on JVM/JS?

noisesmith21:08:04

there's something that clojure internals calls "binding conveyance", where the dynamic vars visible when launching the new thread / async context are imported into that new context when it's created

👍 4
noisesmith21:08:50

here's the magic

user=> (source clojure.core/binding-conveyor-fn)
(defn binding-conveyor-fn
  {:private true
   :added "1.3"}
  [f]
  (let [frame (clojure.lang.Var/cloneThreadBindingFrame)]
    (fn 
      ([]
         (clojure.lang.Var/resetThreadBindingFrame frame)
         (f))
      ([x]
         (clojure.lang.Var/resetThreadBindingFrame frame)
         (f x))
      ([x y]
         (clojure.lang.Var/resetThreadBindingFrame frame)
         (f x y))
      ([x y z]
         (clojure.lang.Var/resetThreadBindingFrame frame)
         (f x y z))
      ([x y z & args] 
         (clojure.lang.Var/resetThreadBindingFrame frame)
         (apply f x y z args)))))
nil

noisesmith21:08:50

beyond the multiple arities, it's very simple

souenzzo21:08:21

then async will use it to control

noisesmith18:08:56

(if you mean core.async, futures, manifold, or something else sanely designed for clojure usage that is)

noisesmith18:08:23

also, dynamic bindings have the right semantics for contextual logging - they work as a stack, so when you escape the binding clause the values go back to their up-stack value