This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-24
Channels
- # announcements (26)
- # babashka (1)
- # beginners (174)
- # calva (1)
- # cider (10)
- # clj-kondo (27)
- # cljtogether (1)
- # clojars (8)
- # clojure (57)
- # clojure-australia (1)
- # clojure-czech (2)
- # clojure-europe (40)
- # clojure-germany (15)
- # clojure-nl (3)
- # clojure-serbia (6)
- # clojure-uk (11)
- # clojurescript (30)
- # conjure (2)
- # cursive (8)
- # datalog (16)
- # datomic (29)
- # emacs (33)
- # etaoin (1)
- # events (2)
- # fulcro (81)
- # funcool (2)
- # integrant (3)
- # jobs (2)
- # joker (2)
- # kaocha (15)
- # lsp (19)
- # malli (8)
- # membrane (1)
- # off-topic (57)
- # pathom (2)
- # reitit (10)
- # releases (1)
- # remote-jobs (2)
- # reveal (5)
- # shadow-cljs (14)
- # sql (11)
- # tools-deps (8)
- # vim (3)
What’s the recommended way to turn Clojure into EDN? I ran into some issues with pr-str
. It works fine with pure data, but less so if data contains lazy seqs. I tried to make naive edn-response middleware for ring. I gave it some lazy seqs (a map containing something that had passed through for
) and this resulted in a string of log messages bundled up with the stringified data :thinking_face: Interestingly, the ring-json-middleware does not have this problem, as cheshire/generate-string does not use printing. Is there a way to produce EDN data that isn’t based on printing, or am I barking up the wrong tree?
https://clojuredocs.org/clojure.core/print-method there is a way to adjust printing for some data based on type in general there is nothing wrong with using pr-str to produce edn. cheshire is not using printing because the serialized form of data not generaly compatible with json specification
I just tried to reproduce and it works just fine for the case like that:
(def x (for [i (range 100)] i))
(type x)
(pr-str x)
could you share a sample that give you a headache?The problem is lazy sequences that do side effects, like logging. When creating a generic tool (like an edn-middleware for Ring), you have no control over what crazy shenanigans the lazy data structures you’re passed will do. So, using pr-str
to generate EDN, might include log statements printed to `*out*` .
Yes, logging is my exact problem 🙂
This reproduces it:
(pr-str
(for [i (range 10)]
(do
(prn i)
i)))
;;=> "(0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0 1 2 3 4 5 6 7 8 9)"
It's impossible to serialize a lazy-seq without realizing it, unless you don't want to serialize the data contained in it?
But to get the serialized string without the printed stuff that should be possible. Hum... Let me check
There's an issue here: https://ask.clojure.org/index.php/2791/captures-stdout-printing-effects-lazily-evaluated-expressions
You should upvote the issue if you want it fixed, the core team does take into account votes for priorities
I'd also recommend upvoting this one: https://ask.clojure.org/index.php/1905/there-should-also-be-writing-in-clojure-edn
👍 Thanks!
FYI you can work around this by first realising the sequence, whilst holding onto its head. This will apply all its effects. Then simply rewalk the structure printing it. Clojure caches the returned values of lazy seqs, so this should work. Obviously it might not be viable for huge datastructures though.
If you go that route, you need to deep-walk it, probably an easy hack around is to actually print it first, and then call pr-str again on it
Does anyone have a snippet that enables http/2 on jetty without using info.sunng/ring-jetty9-adapter
and i really don't want to stray off the "official" path to get something like this working
Hi Clojurians, I wrote a list multiplication program which multiplies two numbers represented as lists using standard multiplication algorithm taught in school. https://www.mycompiler.io/view/E5DB2XN is the first program I wrote. This program helped me pass a bunch of problems on Hackerrank, until it started giving me timeouts at https://www.hackerrank.com/contests/projecteuler/challenges/euler016/problem project euler problem. So, I tried improving the functions with https://www.mycompiler.io/view/4owO1yk shorter but slower attempt. I am not able to figure out why the latter program is slower than the first one. Can anyone help?
In the new attempt there's this code:
(reduce (partial map +) ls)
It doesn't look right.@U2FRKM4TW Yes sir, that is list of products.
It's almost night here, so I'm rather lazy to go through the code right now. But at the very least, that particular part should be written as (apply map + ls)
.
@U2FRKM4TW yes, I already tried that. That was even slower. (apply map + ls)
I can't offer a more constructive advice right now other than "try profiling". Then you'll know for certain.
@U2FRKM4TW thank you Sir. Appreciate that. I will look into profiling.
@U2FRKM4TW I found the cause. It was map
function retuning lazy sequences which delays the execution. I used mapv
at two places and it made it twice faster. Thanks for putting me on the path and letting me explore this lazy sequence angle.
what's the state of core.typed right now? Is anyone using it after its renaissance? is it ready?
The author is interviewed fairly recently here: https://youtu.be/8A8EKTBlFRM which I watched when it came out but unfortunately I somehow don't remember what the summary of the current state is. I know he talks about what he's been working on and I believe has been actively working on core.typed but I'm not sure if those changes are available yet
(unrelated) maybe a malli thing might work well. Like, a subset of what malli can specify might be translatable to typedclojure
It should be pretty easy to translate (lossily) between types and schemas. But inferring either is the really interesting part.
In theory, it can be used to type check Clojure pretty well, but the user ergonomics might annoy you
Since it doesn't have global inference, it just does local inference, and typing Clojure functions often involve complex type defs, since Clojure functions tend to be quite powerful in input
And the core isn't typed, and all libs won't be typed either, so you've always got this type/untyped boundary as well
I'm a type theory expert and I find the types too complicated 😅 But a lot of people like Typescript so 🤷
I don't think its unreasonable to want static analysis of the parts of a spec that can be statically analyzed
> And the core isn't typed, and all libs won't be typed either, so you've always got this type/untyped boundary as well Yeah, but core will be spec'd and typescript balances that fairly well so there is some way forward
and if the whole community weren't osborne effect'ed on spec-2035 it might be possible to get some core ones on board
I don't think you can do a lot of typing with spec no? Cause the predicates rarely map to a logical type?
And if I understand Typescript properly, a hord of devs jumped on it and retrofitted types for a ton of existing JavaScript. I mean this could happen for core.type as well but did not
Also personally, not sure how useful types would be without having abstract data types as the standard compound data-structure.
All maps would still just be of type map. So the issue of like what keys are in this? Am I using a key that doesn't exist? Etc. Would still be there
I think type script has row type polymorphism that can handle this. Not sure what it’s like in practice though
I think row type just means that any superset is automatically valid, even if not explicitly defined as is-a relationship.
Yes that’s my understanding. Don’t know if core typed has this kind of analysis but would love it
Ya I think that's correct. Basically it just let's you say this function works on any type which have at minimum these keys of some given types. But it still requires the type checker to know what keys of what types the object has. So for it to work with maps, it would need that somehow it could infer for any given map at any point in the program what are the keys it would now contain and what types those keys would be of. Which seems like really hard to do. And that ignores that it's possible to have a dynamic key too, like where the key name is coming at run-time from external input