Fork me on GitHub
#clojure
<
2022-10-11
>
sheluchin13:10:21

Is writing server log files as Clojure data structures a common practice in production? I'm curious about approaches like what https://github.com/BrunoBonacci/mulog does.

bruno.bonacci13:10:05

In cloud environments is more common to ship logs/events/traces to cetralised logging systems. And mulog publishers can help you with that.

bruno.bonacci13:10:34

writing local files on ephemeral machines (like the cloud machines) is a recipe for disaster!

sheluchin14:10:51

Thanks, @U0LCHMJTA. I think I mis-phrased my question. What I mean to ask is whether it is common practice to feed Clojure data structures to production logging systems, but now I see that several of the mulog publishers will translate into JSON before sending it off. That makes it more clear. Thank you. I'll find some time to watch the full video soon.

bruno.bonacci14:10:47

ahhh i see. the format depends on the target systems. most systems have JSON REST API. some (like Prometheus) have custom/proprietary formats. Others are binary. EDN capable systems are rare.

zhuxun214:10:33

Is there an idiom for (or foo 42) except the default value 42 is only chosen when foo is nil and not when foo is false?

reefersleep19:10:52

Another fun alternative ( not idiomatic 😅):

(some some? [foo 42])

zhuxun214:10:12

Currently I'm doing (if (nil? foo) 42 foo) but I hate that foo is repeated twice

p-himik14:10:54

If you really hate it, then you can write a macro. But using if is a proper solution here.

hoppy03:10:49

(or foo 42) works, unless you have the outlier of foo being 'false'

Alex Miller (Clojure team)14:10:35

depending on context, fnil may also be useful for nil-patching a function call

elken14:10:59

Yeah was gonna say fnil handles this

borkdude14:10:23

Isn't str/re-quote-replacement supposed to escape dots (or rather, the underlying Java lib)?

user=> (re-matches (re-pattern (clojure.string/re-quote-replacement "..")) "xx")
"xx"

borkdude14:10:24

user=> (clojure.string/replace "xx" (re-pattern (clojure.string/re-quote-replacement "..")) "ff")
"ff"

Alex Miller (Clojure team)14:10:13

why are you using re-pattern?

Alex Miller (Clojure team)14:10:47

the last arg is not an re

borkdude14:10:22

pattern / (string or function of match)

Alex Miller (Clojure team)14:10:54

sorry, I'm mismatching the args, but again, you should be using re-quote-replacement for the last arg

Alex Miller (Clojure team)14:10:48

(clojure.string/replace "xx" (re-pattern "..") (clojure.string/re-quote-replacement "ff"))

borkdude14:10:28

yeah makes sense

simongray14:10:36

How can I quickly and reliably get an io/output-stream at some path if the referenced path doesn’t already exist? Creating an output-stream for a file on-demand works fine if there are no subdirectories, but I need to also create the file when given a path containing subdirectories, e.g path/to/file.ext.

simongray14:10:09

I’m sure there is some quick way to do this, saving me the trouble of writing the code myself…

simongray15:10:14

@alexmiller Thank you, Alex! Exactly what I was looking for.

simongray15:10:13

The Clojure standard library saves the day again!

zalky18:10:42

Hi all: is there any way, given a namespace object, to return the resource (if there is one), which was compiled to produce the namespace? You can check the vars in the namespace object to see if they have a :file attribute in the metadata, but not all the namespaces that are compiled from files will have vars. Some might be computed for side effects, but still have files.

dpsutton18:10:02

( "clojure/core/match.clj")
#object[java.net.URL
        "0x4a2fa566"
        "jar:file:/Users/dan/.m2/repository/org/clojure/core.match/1.0.0/core.match-1.0.0.jar!/clojure/core/match.clj"]

dpsutton18:10:31

you can play around with this notion. Note that it is slightly different than the namespace name.

👍 1
zalky18:10:38

Gotcha. I was hoping to avoid having to think through the edge cases, since presumably Clojure is already doing this to create the namespace. Is it really as simple as just swapping out the . for / and and the -` for _, and then checking for both .clj and .cljc files?

dpsutton18:10:15

i believe so

jpmonettas18:10:32

namespaces are not tied to files, you can have multiple namespaces declared in one file, or a namespace spread thru multiple files (like clojure.pprint)

dpsutton18:10:20

they acknowledged that > (if there is one)

jpmonettas18:10:40

oh, missed that sorry

dpsutton18:10:02

But you’re right. Lots of ways this could work poorly. But in general, will probably work quite a bit

jpmonettas18:10:05

but what if there are multiple?

👍 1
jpmonettas18:10:21

clojure.pprint is one case of that

zalky18:10:16

That is a good point about multiple files. Luckily, in my particular case as long as I can map consistently to the root resource (if there is one), that is sufficient for my purposes.

👍 1
Kelvin21:10:02

OK not sure why I’m getting an ArityException on this custom protocol:

(import '[org.apache.jena.graph Node NodeFactory Triple])

(defprotocol Predicate
  (-create-triple
   [pred subj obj])
  (-add-triple!
   [pred subj obj triples]
   [pred subj obj triples idx]))

(extend-protocol Predicate
  Node
  (-create-triple [p s o]
    (Triple. s p o))
  (-add-triple! [p s o coll]
    (.addTriple coll ^Triple (-create-triple p s o)))
  (-add-triple! [p s o coll idx]
    (.addTriple coll idx ^Triple (-create-triple p s o))))

(let [triple-block (ElementPathBlock.)]
    (-add-triple! (NodeFactory/createVariable "y")
                  (NodeFactory/createVariable "x")
                  (NodeFactory/createVariable "z")
                  triple-block))

; Execution error (ArityException) at com.yetanalytics.flint-jena.triple/eval10084$fn$G (triple.clj:14).
; Wrong number of args (4) passed to: com.yetanalytics.flint-jena.triple/eval12288/fn--12291
The 5-arity version works, but not the 4-arity version

dpsutton21:10:00

you need the this argument

Kelvin21:10:07

I am passing a this argument though. NodeFactory/createVariable returns a Node instance, which serves as the this arg for both the 4- and 5-arity -add-triple! functions.

Kelvin21:10:23

I wonder if this is an issue with extend-protocol. If I switch the order the two -add-triple! impls under Node, then it’s the 5-arity version that throws the exception

hiredman21:10:28

% clj
Clojure 1.11.1
user=> (defprotocol Predicate
  (-create-triple
   [pred subj obj])
  (-add-triple!
   [pred subj obj triples]
   [pred subj obj triples idx]))
Predicate
user=> (doc -add-triple!)
-------------------------
user/-add-triple!
([pred subj obj triples] [pred subj obj triples idx])
nil
user=>

hiredman21:10:59

it is taking your second arity as a docstring

hiredman21:10:51

actually, wait, I think I just forgot how multiple arities show up in doc

Kelvin21:10:56

Aha! Figured it out:

(extend-protocol Predicate
  Node
  (-create-triple [p s o]
    (Triple. s p o))
  (-add-triple!
    ([p s o coll]
     (.addTriple coll ^Triple (-create-triple p s o)))
    ([p s o coll idx]
     (.addTriple coll idx ^Triple (-create-triple p s o)))) 
The issue is that the extend-protocol multiple-arity syntax is slightly different from, say, the defrecord syntax

Kelvin21:10:35

For reference the defrecord syntax would indeed be:

(defrecord SomePredicate [...]
  Predicate
  (-create-triple [this s o] ...)
  (-add-triple! [this s o coll] ...)
  (-add-triple! [this s o coll idx] ...))

Kelvin21:10:48

Why these two syntaxes are different in the first place I have no idea