This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-14
Channels
- # announcements (4)
- # aws (7)
- # babashka (44)
- # beginners (178)
- # calva (15)
- # cider (3)
- # clj-kondo (15)
- # clojure (139)
- # clojure-dev (8)
- # clojure-europe (2)
- # clojure-italy (2)
- # clojure-losangeles (9)
- # clojure-nl (32)
- # clojure-spec (6)
- # clojure-sweden (1)
- # clojure-uk (27)
- # clojurescript (17)
- # core-typed (116)
- # cursive (26)
- # data-science (1)
- # datomic (14)
- # duct (16)
- # emacs (9)
- # events (1)
- # fulcro (47)
- # jobs (3)
- # juxt (6)
- # keechma (2)
- # malli (59)
- # mid-cities-meetup (8)
- # off-topic (32)
- # pathom (5)
- # reagent (2)
- # remote-jobs (4)
- # rewrite-clj (16)
- # shadow-cljs (14)
- # spacemacs (9)
- # sql (27)
- # tools-deps (37)
- # vscode (7)
I'm struggling with a closed stream using clojure.data.csv/write-csv to write to stdout:
(defn -main [& args]
(with-open [w (io/writer *out*)]
(write-csv w [[1 2 3] ["a" "b" "c"]])))
invoked with:
clojure -m
1,2,3
a,b,c
Exception in thread "main" http://java.io.IOException: Stream closed
any ideas?with-open closes its input on exit, usually you don't want to close *out*
@danvingo I tried it in a repl, and replicated the error - if I make a writer out of *out*
, then close it, then clojure crashes the next time it tries to use *out*
Clojure 1.10.1
(ins)user=> (def w ( *out*))
#'user/w
(ins)user=> (.close w)
Error printing return value (IOException) at sun.nio.cs.StreamEncoder/ensureOpen (StreamEncoder.java:45).
Stream closed
Execution error (IOException) at sun.nio.cs.StreamEncoder/ensureOpen (StreamEncoder.java:45).
Stream closed
the solution is don't use with-open
, because you don't want to close it
☝️ Also, you can also use *out*
directly, since it's already a
:
(write-csv *out* [[1 2 3] ["a" "b" "c"]])
That way you don't need to .flush
it, which you would need if you only made a writer from *out*
(i.e. replaced your with-open
with a let
)ah that makes sense about not closing stdout.
Thanks rodolfo, using **out**
direclty worked!
I have a function named page that returns a vector containing two elements. For example, [[:head some-val] [:body some-val]]
however, hiccup.page/html5 accepts a variadic args. So I tried, (apply hiccup.page/html (page))
I’m looking for a better way to log what a function is doing in production. That is, I want a better time
macro that can “snapshot” between various parts of a function and then I should be able to control the logging of the results. I don’t want a benchmarking tool, rather something that will collect fine-grained metrics.
also they have a function-instrumentation example just below the code block instrumentation
Hm, I was more interested in using something that I can weave through a let binding. Mostly for debugging to diagnose network/database bottlenecks.
Here’s my crude approach:
(defn start-stopwatch []
(atom (jt/instant)))
(defn capture-time [time-atom msg]
(let [now (jt/instant)]
(if-let [before @time-atom]
(log/info :msg (str "Time! " msg) :time-ms (jt/time-between before now :millis)))
(reset! time-atom now)))
There are solutions like:
(metric-wrap
(do-something)
(do-something)
(do-something))
and metric-wrap will send data to metric system about time
to send metrics. You have to only choose metric system and probably you will find library for this.can anyone answer this about where STDOUT of native C lib redirected to in the Clojure REPL? https://groups.google.com/forum/#!topic/clojure/FzM3tIphBUw%5B1-25%5D
This depends on what repl you use. For generic clojure.main repls, it will go to the STDOUT and your repl also prints to STDOUT. For a client/server like NRepl (which eg. cider uses) it will go to stdout of the server process, which your editor might be hiding in an unexpected place.
I have a reflection warning I'm trying to resolve but the message includes a line number that is just the first line in the file which makes it difficult to track down the actual problem.
Reflection warning, jackdaw/test/serde.clj:1:205 - call to java.lang.IllegalArgumentException ctor can't be resolved.
Anything I can do to get a better idea of where the problem is?
I vaguely recall that this can mean an error in the ns form of some other ns required from that file - could be wrong though.
Additionally, look for any java iterop calls that might not map to valid java method overrides.
I think so. Unless there's something weird related to Generics. The Serde
below is actually a Serde<T>
.
(ns jackdaw.test.serde
(:require
[clojure.tools.logging :as log]
[jackdaw.serdes.edn :as edn-serde]
[jackdaw.serdes.json :as json-serde])
(:import
(org.apache.kafka.clients.consumer ConsumerRecord)
(org.apache.kafka.common.serialization Serde
Deserializer Serdes Serializer
ByteArraySerializer
ByteArrayDeserializer)
(org.apache.kafka.common.errors SerializationException)))
Nope. Serde
being generic shouldn't be related to importing the symbol. Doesn't look like there's enough information present to help debug.
OK. Thanks for the suggestions. I guess I'll skip this one for now. There's 100s of others to fix 🙂
Why you bothering type hinting everything? It generally barely adds any overhead, unless in a loop
The warnings produced when loading the library are getting a bit overwhelming. I’d be interested in knowing how to selectively enable the warnings to cover only performance sensitive parts of the code base but didn’t think that was an option
I'm stumped on this. I have a function that returns a lazy sequence (let's call
it lzs - it's produced by another function, and for this exercise I def'd it
in the REPL from `*1'). It's a sequence of maps.
When I apply a merge-with operation to the lazy sequence. I get the following
error.
class clojure.lang.PersistentHashSet cannot be cast to class
java.lang.Comparable (clojure.lang.PersistentHashSet is in unnamed
module of loader 'app'; java.lang.Comparable is in module java.base
of loader 'bootstrap'
If I apply the same operation on a `doall' of the sequence, I also get the error.
However, if I fully realize the sequence in the REPL and feed it into the
merge operation, I don't get the error. There's really no magic in the merge-with
operation, it just conj's some sets.
Any ideas?
The relevant code is below:
;; FAILS
(apply
merge-with
px-tran-netter-ex
lzs)
;; FAILS
(apply
merge-with
px-tran-netter-ex
(doall lzs))
;; NO PROBLEM HERE with lzs realized and fed back in
(apply
merge-with
px-tran-netter-ex
'({:fund {:src-ax-id #{nil :ax-m01}}}
{:fund {:src-ax-id #{:ax-m01}}}
{:fund {:src-ax-id nil}}
{:fund {:src-ax-id :ax-m01}}
{:fund {:src-ax-id #{:ax-m01}}}
{:fund {:src-ax-id #{nil :ax-m01}}}
{:fund {:src-ax-id #{:ax-m01}}}
{:fund {:src-ax-id nil}}
{:fund {:src-ax-id :ax-m01}}
{:fund {:src-ax-id #{:ax-m01}}}))
The px-tran-netter-ex is
(defn px-tran-netter-ex
[ov nv]
(if (nil? ov)
nv
(update
ov
:src-ax-id
(fn px-tran-set-merger
[lv rv]
(if (some? rv)
(conj
(if (set? lv)
lv
(if (some? lv)
#{lv}
#{}))
rv)
lv))
(:src-ax-id nv))))
If this helps, here it is. The original sequence is returned by a `for'
#error {
:cause "class clojure.lang.PersistentHashSet cannot be cast to class java.lang.Comparable (clojure.lang.PersistentHashSet is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')"
:via
[{:type clojure.lang.ExceptionInfo
:message nil
:data #:clojure.error{:phase :print-eval-result}
:at [clojure.main$repl$read_eval_print__9086 invoke "main.clj" 442]}
{:type java.lang.ClassCastException
:message "class clojure.lang.PersistentHashSet cannot be cast to class java.lang.Comparable (clojure.lang.PersistentHashSet is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')"
:at [clojure.lang.Util compare "Util.java" 153]}]
:trace
[[clojure.lang.Util compare "Util.java" 153]
[clojure.lang.RT$DefaultComparator compare "RT.java" 283]
[clojure.lang.PersistentTreeMap doCompare "PersistentTreeMap.java" 330]
[clojure.lang.PersistentTreeMap entryAt "PersistentTreeMap.java" 317]
[clojure.lang.PersistentTreeMap containsKey "PersistentTreeMap.java" 97]
[clojure.lang.APersistentSet contains "APersistentSet.java" 34]
[clojure.lang.PersistentTreeSet cons "PersistentTreeSet.java" 68]
[clojure.lang.PersistentTreeSet cons "PersistentTreeSet.java" 17]
[clojure.lang.RT conj "RT.java" 677]
[clojure.core$conj__5390 invokeStatic "core.clj" 85]
[clojure.core$conj__5390 invoke "core.clj" 82]
[user$px_tran_set_merger invokeStatic "scratch.clj" 202]
[user$px_tran_set_merger invoke "scratch.clj" 197]
[clojure.core$update invokeStatic "core.clj" 6198]
[clojure.core$update invoke "core.clj" 6188]
[user$px_tran_netter invokeStatic "scratch.clj" 219]
[user$px_tran_netter invoke "scratch.clj" 215]
[clojure.core$merge_with$merge_entry__5962 invoke "core.clj" 3063]
[clojure.core$reduce1 invokeStatic "core.clj" 944]
[clojure.core$merge_with$merge2__5964 invoke "core.clj" 3066]
[clojure.lang.ArrayChunk reduce "ArrayChunk.java" 58]
[clojure.core$reduce1 invokeStatic "core.clj" 942]
[clojure.core$reduce1 invokeStatic "core.clj" 934]
[clojure.core$merge_with invokeStatic "core.clj" 3059]
[clojure.core$merge_with doInvoke "core.clj" 3051]
[clojure.lang.RestFn applyTo "RestFn.java" 139]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$apply invoke "core.clj" 660]
[user$eval61811$fn__61813 invoke "scratch.clj" 295]
[clojure.core$keep_indexed$keepi_8568$fn_8569 invoke "core.clj" 7378]
[clojure.lang.LazySeq sval "LazySeq.java" 42]
[clojure.lang.LazySeq seq "LazySeq.java" 58]
[clojure.lang.RT seq "RT.java" 535]
[clojure.core$seq__5402 invokeStatic "core.clj" 137]
[clojure.core$print_sequential invokeStatic "core_print.clj" 53]
[clojure.core$fn__7310 invokeStatic "core_print.clj" 174]
[clojure.core$fn__7310 invoke "core_print.clj" 174]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[clojure.core$pr_on invokeStatic "core.clj" 3674]
[clojure.core$pr invokeStatic "core.clj" 3677]
[clojure.core$pr invoke "core.clj" 3677]
[clojure.lang.AFn applyToHelper "AFn.java" 154]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$prn invokeStatic "core.clj" 3714]
[clojure.core$prn doInvoke "core.clj" 3714]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.main$repl$read_eval_print__9086 invoke "main.clj" 442]
[clojure.main$repl$fn__9095 invoke "main.clj" 458]
[clojure.main$repl invokeStatic "main.clj" 458]
[clojure.main$repl_opt invokeStatic "main.clj" 522]
[clojure.main$repl_opt invoke "main.clj" 518]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]]}
In px-tran-netter-ex
, you're basically doing something like (conj #{:ax-m01} #{:ax-m01})
. If that's indeed what you want (having a set of sets of sets of sets etc), it should work fine where the first set is a hash set. But somewhere along the way, you use a tree set. And that's where it fails.
A tree set tries to compare its items between each other. And sets cannot be compared, so a set cannot be a member of a tree set.
Thanks. The px-tran-netter-ex is a big reduction of the original. I wanted to reduce the problem to its simplest manifestation. (There's further processing that runs some checks/reductions on the sets of sets). I'll have to go looking for the tree set. I reckon it's got to be in the `for' somewhere. Let me do some digging.
Just to make sure - are you sure you want to conj
all those sets under the :src-ax-id
key and not just combine them all with into
or something like that?
Also, if you often find yourself processing deeply nested data structures, https://github.com/redplanetlabs/specter should make your life much easier.
Unfortunately, I do need the excessive conj'ing. There are downstream checks regarding whether the final set members are similar enough to be acceptable. I use specter in other places. I like it.
Just closing this out. There was a PersistentTreeSet way down in the values and a conj was complaining. However, is it just me, or is the behavior of HashSet and TreeSet a little bit inconsistent?
;; returns #{nil #{:a} :a} as clojure.lang.PersistentHashSet
(conj
(clojure.lang.PersistentHashSet/create (list nil :a))
(clojure.lang.PersistentHashSet/create (list :a)))
;; throws clojure.lang.PersistentTreeSet cannot be cast to class java.lang.Comparable
(conj
(clojure.lang.PersistentTreeSet/create (list nil :a))
(clojure.lang.PersistentTreeSet/create (list :a)))
;; returns #{nil :a #{:a}} as clojure.lang.PersistentTreeSet
(letfn
[(Cfn [v1 v2](if (= v1 v2) 0 1))]
(conj
(clojure.lang.PersistentTreeSet/create
Cfn (list nil :a))
(clojure.lang.PersistentTreeSet/create
Cfn (list :a))))
;; returns #{nil #{:a} :a} as clojure.lang.PersistentHashSet
(letfn
[(Cfn [v1 v2](if (= v1 v2) 0 1))]
(into
#{}
(conj
(clojure.lang.PersistentTreeSet/create
Cfn (list nil :a))
(clojure.lang.PersistentTreeSet/create
Cfn (list :a)))))
;; returns #{nil #{:a} :a} as clojure.lang.PersistentHashSet
(letfn
[(Cfn [v1 v2](if (= v1 v2) 0 1))]
(clojure.lang.PersistentHashSet/create
(seq
(conj
(clojure.lang.PersistentTreeSet/create
Cfn (list nil :a))
(clojure.lang.PersistentTreeSet/create
Cfn (list :a))))))
All seems sensible if I supply a comparator that essentially returns 'same' or 'different'And a different `pr-str' representation to differentiate the two. I wonder is there a reason there isn't. Doesn't that break the pr-str / read-string 'loop'.
> is the behavior of HashSet and TreeSet a little bit inconsistent? Their behavior should not be consistent - they are different data structures. They are consistent w.r.t. operations on sets. > a different `pr-str' representation It is expected as well. > Doesn't that break the pr-str / read-string 'loop'. The loop has never been not broken. You can print lots of stuff that's not possible to read at all.
But, it does seem odd that by defining a yes/no comparator rather that the equal/less/more one it allows the conj operation to proceed. Isn't the comparator properly part of the type?
Data types have a domain of definition. By tweaking a type, you're also tweaking its domain of definition.
I don't know a great deal about type systems I'm afraid (that's one of the reason I love Clojure). I'll have to think about this a bit, and the probably a bit more. I don't know why, but it just makes me feel "uneasy". Thanks for the help. Much appreciated.
No problem. Another example - primitive arrays. An array is an array. However, once you create an array of a specific primitive type, you cannot put anything in there but the values of that type.
I think my unease comes down to this
(conj
(clojure.lang.PersistentTreeSet/create
(fn[v1 v2](if (= v1 v2) 0 1))
(list nil :a))
(clojure.lang.PersistentTreeSet/create compare (list :a)))
To my amateur eye, the first treeset and the second are intuitively different types.
They `compare' differently. Whereas, if I use the default comparator, I'd say they were the same type, but the conj blows up.
If I think about your primitive array example, it's like the integer I'd
like to add would be using different `math'.
I suppose if I look at conj as 'join these things as best you can' rather
than a straight append, it's a little easier for me to grasp. I might just replace
the conj using the treeset with a conj-with-compare function, so I remember when I see it next time. (And I will forget).BTW: do you know the best way to cast a tree set to a has set? Or is my seq with create the way to go?
You can create tree sets more easily with sorted-set
and sorted-set-by
.
Probably the easiest way to convert any sort of collection to a hash set is to (into #{} coll)
.
Continuing my type hinting journey, I have some code that produces one of these.... https://kafka.apache.org/21/javadoc/org/apache/kafka/clients/producer/ProducerRecord.html I'm getting a warning that the constructor can't be resolved. This is due to the key and value parameters not being hinted. These are parameterized types <K>, and <V>. Is it actually possible to provide a hint that addresses these warnings?
I doubt that this is because of K and V, because generics literally only exist in javac, and are only present as metadata by the time you are emitting clojure bytecode
there is evil/bad code that inspects the metadata of generics, but that error wouldn't happen here, via the clojure compiler
Looking at the constructors, they all take a K and V, I think hinting the other (statically known per constructor) args would suffice to eliminate this warning
because the root issue here is that clojure's compiler wants to pick which constructor method to emit bytecode for, knowing K and V doesn't actually help there
loop
eagerly performs iteration. It does not return any value at all until the last iteration is performed. It might access the value of lazy sequences in its code.
for macro expansion, is the behavior of the clojure compiler similar to clojure.walk/macroexpand-all instead of clojure.core.macroexpand ?
Good, that's a relief... I had a bug that was solved by adding a Timbre info
statement accessing the data. Luckily it stayed resolved even after removing that again. Some days I question my sanity.
@zilti (thanks for covering for me @alexmiller) sorry about the docs, but simply core.typed is in heavy development to catch up with my years of research I did for my phd. don't use it for anything yet. but wish me luck!
Good luck!
I'm considering core.typed dead, but I'm reviving it in a new project called core.typed xD I haven't heard anyone seriously using core.typed for several years
Do you want to share where it is heading or is that too early?
I'll make this clearer in the readme. Did you manage to find your way to the clojure/core.typed readme? that's the main one now
1. custom typing rules for macros. basically you write something that looks like a macro, but takes a (partially expanded) tools.analyzer-like AST and an expected type, and returns an AST with a type attached. you have complete control/responsibility for type checking/macroexpansion. working on first getting a feel for this system by porting all the special rules I already have for various internal forms to this system, then I'll figure out a decent abstraction for users to define their own typing rules.
Sounds very powerful! I'm guessing you could do this on a form by form basis given a certain context (available vars etc). I would love to use htat
yes the extension point is the fully qualified symbol for the current macro being expanded.
Good luck! 🙂 I am actually trying to use it for a small project right now, and it works, I only have to figure out the annotation "language" again
@ambrosebs do you have funding channels that we can contribute to? This seems impossible without money from interested people
2. symbolic execution. basically there's a bunch of clojure idioms at are really hard to type check with vanilla "bidirectional type checking". like (`let [f #(inc %)] (f 1))` they just need a bit of massaging. some are much more interesting like (update m :a #(+ %1 %2) 2)
for the small price of undecidable type checking (lol) we can add symbolic execution to the type checking algorithm to reduce these to things like (inc 1)
and (assoc m :a (+ (get m :a) 2)
@dpsutton thanks for asking. definitely not impossible and it'll happen one way or another, but see here to support me https://www.patreon.com/ambrosebs
@ambrosebs Do you have something for companies? Something like opencollective?
It's the only one I know that allows a company to give giftcards to their employees for them to spend
Patron is nice, but it relies on individuals and it's (more) cumbersome for companies
OpenCollective also has a nice system that gives exposure to companies. Who sponsored what
I'll make sure you get some funding on OpenCollective 🙂
I would like to give Giftcards to all employees and let them decide what and where to spend. This is possible via OpenCollective. It just needs a bit more interesting Clojure projects
It's still experimental, but boot-clj has it like this https://github.com/boot-clj/boot#sponsors
I don't know why Github Sponsors doesn't have something like this
Has anyone used clojure with azure app insights telemetry API and can give me some insight on how to implement it?
it auto-resolves the namespace of the keyword, uses [reitit.core :as r]
at the top of the file
H2, Redis, Datascript, etc.
RocksDB also fast
if it's simple enough, you can just use a hash-map in an atom
Regular maps/sets/vectors also work as an in-memory db of course. I assume you decided not to use them because you need database-like queries?
Datascript also has a more interesting query language. Datomic also has an in memory version if I remember correctly (since its work).
IIRC datomic and tonsky's Datascript lib both implement versions of the db paradigm as described in the alice book http://webdam.inria.fr/Alice/ which is called "datalog"
oh right, datalog is the query language, Datascript and Datomic both support versions of it https://en.wikipedia.org/wiki/Datalog
Yes, I personally like it quite a bit better than SQL. Its a non turing complete logic language subset that is guaranteed to complete and not go into infinite recursion. Unlike mini kanren :)
Do you happen to know if there are any proven results on "time complexity' of datalog? I can look for such results myself, but if you know of them. e.g. is it provable that every datalog query can be executed in at most polynomial time in the "size of the database", or "size of the query"?
Or a separate but maybe related question: There are regular languages, context-free languages, context-sensitive languages, and "the languages recognizable by Turing machines" (recursively enumerable might be a correct term, but I'm on thin ice there). Is there a similar kind of know sets of "query power", like "SQL queries", "datalog queries", "Turing machine queries", probably in that order of "everything an earlier one can do, a later one can also do, but the later one can do more, too"? If so, are there other well known "query powers" in between those?
I looked through some of the research on Datalog (there is quite a lot) but it's old enough that I think the proofs of that guarantee given a finite set will take more sleuthing. All the academic papers I read (lightly) started with that as a presumption or discussed other matters (such as boundedness). The largest difference between Datalog and SQL is that Datalog is recursive, if you remove that they should be equivalent (although SQL99 was inspired to attempt to add recursion). It's the recursion that gives it more expressive power ... and yes, I think you could use expressiveness as a metric there.
it's really cool that the Alice book is officially free online
I've only read parts of it, but learned a lot from what I read
Thx for the link, have not read that one.
Currently exploring logic programming by writing a state machine to handle media publishing ...so love finding new material in the domain to read through.
is there anything like a drop-while-last
? same semantics of a drop-while but from right to left