This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-02
Channels
- # beginners (130)
- # calva (3)
- # cider (13)
- # circleci (1)
- # cljsrn (19)
- # clojure (106)
- # clojure-europe (10)
- # clojure-losangeles (1)
- # clojure-nl (9)
- # clojure-uk (33)
- # clojurescript (16)
- # code-reviews (24)
- # conjure (11)
- # cursive (41)
- # data-science (9)
- # datomic (63)
- # fulcro (19)
- # graphql (12)
- # helix (4)
- # kaocha (2)
- # leiningen (3)
- # malli (8)
- # meander (1)
- # off-topic (17)
- # re-frame (16)
- # reitit (12)
- # sci (32)
- # shadow-cljs (73)
- # spacemacs (31)
- # sql (38)
- # tools-deps (26)
- # xtdb (28)
Hi guys, I tried searching everywhere but what unicode encoding in Clojure using? It doesn't seem to be UTF-8
Clojure reads in source files as utf8, jvm characters are internally utf16, other io on the jvm if you don't explicitly specify an encoding will use an os dependent default
Since Java 9, at least Hotspot, and perhaps other JVMs, use 8-bit characters for strings that contain only code points in the range [0, 127], as a space optimization.
Java/JVM also defaults to Big Endian (“network byte order”) everywhere it can and no BOM is used.
in general, Clojure relies on the host (Java) and does what Java does wrt char encodings
different apis and libs usually depend either on your default encoding or UTF-8 if you don't override. You can see default encoding with (System/getProperty "file.encoding")
Alright Thank you! (I figured out what I was looking for. Or rather I think my eyes had been playing tricks on me)
the version of unicode is totally dependent on the jvm version you're using
Hi, I'd like to better understand the difference between how a recursive function using lazy-seq
differs from what for
returns. My experience is that with lazy sequence returned by for
is that when iterating it with loop
the portion of the sequence that gets evaluated remains referenced in some way, so that none of the elements from previous iterations are garbage collected. This is assuming the application's iteration code doesn't involve retaining a reference, of course.
I've got some example code that shows the difference through causing an OOM in the for
case. https://gist.github.com/Hamled/cab41245abd208b4f6cb67026f135e34 (The gist also has some examples of how this interacts weirdly with futures from the manifold library, in case anyone has used that and has some insights... that's more representative of my actual use case.)
Oh maybe this is a result of for
using chunk-cons
? When I change the parameters of my example code so that the sequence is 100 elements long, but the total amount of memory allocated is still the same, the for
version also works.
I guess if the amount of memory needed for all entries in single chunk is more than can be allocated, then it OOMs?
to be clear, for is not a loop and doesn't use looping internally - it is built out of "recursive" calls that are lifted out via lambda encapsulation
IOW exactly how you'd use lazy-seq and self calls in any other lazy function you construct
for, or a lazy-seq, only causes OOM if you are irresponsible about holding the return values and preventing GC (outside pathological cases where a single element blows the RAM)
by binding the result of
apologies - clearly I'm not fully awake yet, you were using for in defn, not def, so that isn't the issuefor
in a top level def
, you ensure that the vm's GC can never reclaim any value used in the lazy seq it generates, that is the source of your OOM and the answer is to never do that
(you'd get the same problem, but faster, if you used loop
to build the equivalent non-lazy list)
This classic blog post (about concat) describes so gotchas with lazy-seqs and imperative code. I think with a slight change of perspective it can also offer some insight about using resource-intensive or side effecting functions inside lazy code https://stuartsierra.com/2015/04/26/clojure-donts-concat
Yeah the issue here is definitely that the design of my code is resulting in a reference to the head of the lazy sequence. I have some code that produces a sequence of messages representing server responses for a TCP server, and another layer that calls that code and puts each message into the stream representing the socket. To best separate these layers I was hoping to just return a lazy sequence in the one case where I have a lot of messages, but it seems like I cannot implement some code that iterates that lazy sequence without ultimately keeping the entire thing in memory.
there are ways to do it carefully, but I think the simplest thing is not to use laziness when you need precise control of resource usage
core.async is often used incorrectly or for the wrong things, but backpressure on execution to control resource utilization is something it can do well (though manifold which you are using already can arguably do that even better...)
Yeah, I think that's what I assumed was happening with the design I had previously. It was working fine until I changed something to actually wait on the final result of putting all the messages into the stream.
So my solution now involves providing a function that can be iteratively called to produce the next message to put into the stream. This seems to be working great, and I think it's an acceptable design (really I was just hoping to keep stream-related concepts out of the business logic). I am curious though, you mentioned it would possibly have been possible to use a lazy sequence if it was carefully done. Do you have any suggestions on stuff I could read to understand how that might have worked? Thanks again for the help!
in general, I would not use lazy seqs to do things over a buffer, I would use loop/recur to have better control over when things happen
with lazy seqs, you give up control over when realization happens (chunking usually happens in chunks of 32)
Has anyone written a plugin for JetBrains/Intellij in Clojure, or know of any resources/tutorials by people who have?
yes, it's called Cursive, discussed in #cursive
Tangential, but there's also Clojure-Kit for IDEA which seems to work for those people who can't deal with Cursive...highly subjective and I have no idea why, but there's an option 🙂
I've tried it once when figuring out if clj-kondo could work together with it (it did)
Using the tick library I'm not seeing a better way to determine whether something is a date-time than testing for instance of either java.time.Instant
or java.time.LocalDate
. Am I missing anything?
(ins)user=> (set/intersection (supers java.time.Instant) (supers java.time.LocalDate))
#{java.time.temporal.TemporalAdjuster java.time.temporal.TemporalAccessor java.io.Serializable java.time.temporal.Temporal java.lang.Object java.lang.Comparable}
I don't know all the libs and classes in play here intimately, but usually the interface or superclass you want would be in that set
java.time.temporal.Temporal smells correct
It is a localdatetime. Fair point about wrappers though. I often just use https://github.com/henryw374/cljc.java-time if I'm not so familiar with some part of the api and move to tick once I know what I'm doing and want some sugar.
(This is primarily why I don't use wrappers for java.time, and prefer interop. Libraries seem to invent terminology without carefully understanding the stuff they wrap)
thanks. i guess i was more wondering if I was missing some kind of predicate like time?
or date?
so that i don't reinvent
I'm in the world of checking classes … but thanks for the pointer to Temporal, I'm not sure I would have thought to go hunting for the base class
the real problem is many wrapper library authors don't think of that either, the best thing as @ghadi says is to not use a wrapper, or just check what the library is using (which is often disappointing, I agree)
but maybe you try the superclass it works and you can move on
actually i probably don't need a wrapper … i'm just potentially passing dates/times around from a database and doing some comparisons
How do you run tests in shell for reflections
with deps.edn
? I would like to fail build when code has reflections.
thanks, I would like to see in README what check
check 🙂 It is a little mysterious 🙂
Is it checking formatting? I don’t want to fail build when formatting is not as clj-check wants it
lein help check
-> Check syntax and warn on reflection.
As far as I recall, it just checks for reflection warnings (https://github.com/athos/clj-check/blob/master/src/clj_check/check.clj#L14-L15)
You'll want to check that you get a non-zero exit code for reflection warnings -- it may only give a non-zero exit code for compilation failures.
Ah, it does not:
(! 773)-> clojure -A:check
Compiling namespace check.example
Reflection warning, check/example.clj:7:3 - call to method append on java.lang.String can't be resolved (no such method).
Thu Jul 02 14:06:26
(sean)-(jobs:0)-(~/clojure/example)
(! 774)-> echo $?
0
So it won't fail the build for you.it also hang forever
clj -Acheck
Jul 02, 2020 11:05:38 PM api.core invoke
INFO: app start K_REVISION: nil
Jul 02, 2020 11:05:38 PM api.core invoke
WARNING: HOST variable is not set!
It looks like it not only load namespaces but also run main
functions so start the server
No, it only loads namespaces.
So you must be doing something in a def
form that causes your server to start.
I bet you do. There's nothing in clj-check
that runs any functions. It just loads files.
Nope. check
works just fine. The problem is in your code.
Wait for 60 seconds and see if it exits. You may be starting thread processes just by loading namespaces, and clj-check
does not include shutdown-agents
so it will wait for threads to cleanly shutdown, instead of just exiting.
:check {:extra-deps {athos/clj-check {:git/url ""
:sha "b48d4e7000586529f81c1e29069b503b57259514"}}
:main-opts ["-m" "api.core"]}
README show I should use main-opts
and I am 99,9% sure it runs main
functions, because I see (l/info "app start K_REVISION:" (System/getenv "K_REVISION"))
No, the readme has this
:main-opts ["-m" "clj-check.check"]}}
YOU are running your own main function
Define "doesn't work".
Compiling namespace spec.utils
Compiling namespace spec.common
Execution error (FileNotFoundException) at clj-check.check/check-ns (check.clj:15).
Could not locate clojure/test/check/generators__init.class, clojure/test/check/generators.clj or clojure/test/check/generators.cljc on classpath.
(! 767)-> clj -A:new app check/example
Downloading: seancorfield/clj-new/maven-metadata.xml from clojars
Generating a project called example based on the 'app' template.
Thu Jul 02 14:05:28
(sean)-(jobs:0)-(~/clojure)
(! 768)-> cd example/
Thu Jul 02 14:05:30
(sean)-(jobs:0)-(~/clojure/example)
(! 769)-> clojure -A:check
Compiling namespace check.example
Thu Jul 02 14:05:39
(sean)-(jobs:0)-(~/clojure/example)
(! 770)-> vi src/check/example.clj
Thu Jul 02 14:06:11
(sean)-(jobs:0)-(~/clojure/example)
(! 771)-> clojure -A:check
Compiling namespace check.example
Reflection warning, check/example.clj:7:3 - call to method append on java.lang.String can't be resolved (no such method).
(I added (.append "Hello" "World")
in vi
to force a reflection warning)@U0WL6FA77 Your output shows it is working perfectly.
You forgot to provide aliases to add the dependencies you need.
I expect your spec.common
namespace is requiring clojure.test.check
and you didn't have -A:test
to add that dependency?
You need to be more methodical and take more careful steps when you are debugging.
I know this is bad explanation, but I am really tired, because of some private reasons. But I am going on holidays in July so I will recover 🙂
Enjoy your vacation! Definitely sounds like you need it! Unwind, and come back refreshed.
Once you get this figured out, you could run clojure -A:check 2>&1 > check.log
and if there are compilation errors, that should fail the build, then do fgrep -v Compiling check.log | fgrep -v Reflection
which should have a zero status if there are no reflection warnings, and a status of 1 if there are -- which should fail the build (assuming it fails on any non-zero exit status for any command)
Reflection warning, bidi/bidi.cljc:20:31 - call to static method decode on java.net.URLDecoder can't be resolved (argument types: java.lang.String, unknown).
Oh I guess I can’t really fail, because of dependencies reflections which I can’t changeI've started playing with https://github.com/gnl/ghostwheel, and I like it so far, except that my clojure-mode
in emacs doesn't indent it like defn
. Does anybody know how to fix that?
you can try editing the clojure mode variable clojure-defun-indents
by putting
(put-clojure-indent 'some-symbol :defn)
in you .emacs
presumably (put-clojure-indent '>defn :defn)
based on your link
Are entries of map literals evaluated in order?
E.g. is it guaranteed that delete!
will occur before insert!
?
{:del (delete! ,,,)
:ins (insert! ,,,)}
clojure is always evaluated left to right, but putting side effects in map entries is just weird - I'd expect that to work but use let anyway for clarity
oh! - the reader constructs the map before the resulting form is evaluated, so I think it could reorder (testing...)
"Vector elements are evaluated left to right, Sets and Maps are evaluated in an undefined order."
@nikolavojicic @jkr.sw yeah - the reader reorders before the side effects happen
user=> {:a (println "a") :b (println "b") :c (println "c") :d (println "d") :e (println "e") :f (println "f") :g (println "g") :h (println "h") :i (println "i") :j (println "j") :k (println "k") :l (println "l") :m (println "m") :n (println "n") :o (println "o") :p (println "p") :q (println "q") :r (println "r") :s (println "s") :t (println "t") :u (println "u") :v (println "v") :w (println "w") :x (println "x") :y (println "y") :z (println "z")}
y
q
r
v
o
n...
It is a localdatetime. Fair point about wrappers though. I often just use https://github.com/henryw374/cljc.java-time if I'm not so familiar with some part of the api and move to tick once I know what I'm doing and want some sugar.