This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-12-06
Channels
- # adventofcode (54)
- # announcements (3)
- # babashka (34)
- # beginners (38)
- # calva (27)
- # cherry (5)
- # clj-kondo (34)
- # clojure (26)
- # clojure-bay-area (4)
- # clojure-berlin (3)
- # clojure-europe (26)
- # clojure-india (6)
- # clojure-nl (1)
- # clojure-norway (54)
- # clojure-uk (2)
- # conjure (3)
- # cursive (4)
- # data-science (1)
- # emacs (6)
- # events (4)
- # fulcro (2)
- # hugsql (6)
- # hyperfiddle (38)
- # lsp (3)
- # matrix (1)
- # membrane (5)
- # off-topic (27)
- # re-frame (3)
- # releases (1)
- # sci (8)
- # shadow-cljs (34)
- # squint (132)
I have been struggling with with vscode/calva/clj-kondo setup and I cannot tell why I am getting the warning Namespace name does not match file name: craigslist-art-gallery.core clj-kondo(namespace-name-mismatch)
in the file src/craigslist-art-gallery/core.clj
since the filename and ns appear to match. Paring it down to a very minimal project directory containing nothing but a core.clj
file that only creates the craigslist-art-gallery.core
ns and a deps.edn
that specifies src
under the :paths
key has not clarified what could be causing the issue. Classpath seems to be correct. Context in thread.
here is some context on what I have: a namespace in a file and a deps.edn
that I would expect to properly set up the classpath results in the clj-kondo CLI to mark a warning about this mismatch:
(base) ➜ craigslist-art-gallery> pwd
/Users/dbasner/workspace/craigslist-art-gallery
(base) ➜ craigslist-art-gallery> cat deps.edn
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.11.1"}}}
(base) ➜ craigslist-art-gallery> clojure -Spath
src:/Users/dbasner/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:/Users/dbasner/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar:/Users/dbasner/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar
(base) ➜ craigslist-art-gallery> cat src/craigslist-art-gallery/core.clj
(ns craigslist-art-gallery.core)
(base) ➜ craigslist-art-gallery> clj-kondo --classpath "$(clojure -Spath)" --lint /Users/dbasner/workspace/craigslist-art-gallery/src/craigslist-art-gallery/core.clj
/Users/dbasner/workspace/craigslist-art-gallery/src/craigslist-art-gallery/core.clj:1:5: error: Namespace name does not match file name: craigslist-art-gallery.core
linting took 35ms, errors: 1, warnings: 0
oh duhhhh
I’ve spent so long staring at this, thank you hiredman I appreciate it!
Hi folks. I hit a problem with https://github.com/clojure/java.data Long story short - we are parsing some data from k8s java client to edn, change it and then want to create java instance from that map. Here is my simple code
defmethod data/to-java [V1Job clojure.lang.APersistentMap] [clazz props]
(doto (V1Job.)
(.apiVersion "batch/v1")
(.kind "Job")
(.metadata (data/to-java V1ObjectMeta (:metadata props)))
(.spec (data/to-java V1JobSpec (:spec props)))))
But inside the spec (V1JobSpec) we have a template (V1PodTemplateSpec) and inside of it there is spec (V1PodSpec) where we have
......
containers: clojure.lang.LazySeq@d094320b
......
Then when I run this code in k8s I have
{"reason":"FieldValueRequired","message":"Required value","field":"spec.template.spec.containers[0].name"},
{"reason":"FieldValueRequired","message":"Required value","field":"spec.template.spec.containers[0].image"}
but in the edn i do have the name and the image. Is there a way I can force the evaluation of this LazySeq that was assigned to the java object? Or not create it at all?Sounds like it's trying to convert that to a string for printing?
Can you provide a bit more context for that specfiic part of the to-java
process? Can you call vec
on the :containers
fields?
@U04V70XH6 vec
is solving the problem, yes, I was just worried that for other objects we might have the same problem. I’m using the to-java
from java.data and when I override it it’s just the part that I shared, nothing more and tbh I don’t really know how this lib works.
hello guys, i am learning about concurrency
,
i have started reading The Java™ Tutorials
and write the java code in clojure;
so far i reached the "producer - consumer" concept, but the problem is that my threads are blocking each other somehow
the link for the lesson is here : https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
my code is here: https://github.com/sandre1/clj-training/blob/main/java-concurrency/src/concurrency/producer_consumer.clj
You can start calva and execute producer-consumer
function
I tried with clojure locking
function, locking different Object.
for synchronized
methods, without success
Expected result:
Start
...
(some println-s for feedback)
...
MESSAGE RECEIVED: Mares eat oats
MESSAGE RECEIVED: Does eat oats
MESSAGE RECEIVED: Little lambs eat ivy
MESSAGE RECEIVED: A kid will eat ivy too
DONE!
Stop
on your clojure repl, you can hit Ctrl-\
to see a thread dump, where you can check all the threads stacks and see if they are waiting for a lock for example, which can help you debug this kind of code
ctrl+\ just opens the current tab in a new tab
do you have an extension for the thread dump, maby?
or if you use a debugger like http://www.flow-storm.org/ you have features like the https://flow-storm.github.io/flow-storm-debugger/user_guide.html#_timeline_tool to help you debug those kinds of things
ctrl+\ just opens the current tab in a new tabthat should be in a terminal repl
also you can use https://visualvm.github.io/ to connect to any jvm process and do a thread dump, heap dump, monitor you GC and more
visualvm is what I tend to use for thread dumps, since you just run the program, double click on your process then click the Threads tab, and there you have a Thread Dump button
ok, thank you. i will check it
clojure functions are Runnables so you can pass them directly to things like the Thread constructor without needing to reify Runnable
you have an immutable data structure and are always printing out the first thing in it, and since the datastructure is immutable the first thing is always the same misread
it is likely https://github.com/sandre1/clj-training/blob/main/java-concurrency/src/concurrency/producer_consumer.clj#L55 that is a race condition, you are only continuing to loop if the message returned by take is the same as the value of message-global, which take just woke up the publisher to overwrite
in general I would recommend, if you are following the java tutorial, to stick to it more closely, e.g. make something that is a "Drop" and make a new drop and pass it in to the thing that makes producers and consumers. that will help avoid various things that can happen in the repl when you have global locks (you have an old thread running, holding the lock, then try to start a new thread and nothing happens)
or you could just go straight to using https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/SynchronousQueue.html which is almost but not entirely exaclty Drop (drop is a blocking queue with a internal buffer / capacity of 1, SynchronousQueue has a capacity of 0)
thank you for the review, i modified part of the code so it consumes all the messages from the producer.
still i have a problem with the threads, one/both are not closing.
so after the threads are started, no
"Stop" will print
https://github.com/sandre1/clj-training/blob/main/java-concurrency/src/concurrency/producer_consumer.clj
you moved the recur outside the when so it loops forever https://github.com/sandre1/clj-training/blob/main/java-concurrency/src/concurrency/producer_consumer.clj#L62
Can someone help me understand programming with streams? I've seen code like this in advent of code:
(let [in (line-seq (java.io.BufferedReader. *in*))]
(println "Part A:" (transduce xf conj '() in)))
I don't understand how/when the program considers end of stream, does it wait for a explicit end, similar to EOF in a file?line-seq
returns a lazy sequence of lines. Underneath the hood, line-seq
uses the .readLine
method from BufferedReader. It keeps reading until readLine
returns null which is how it signals that it's done.
For unix-like systems, all file operations eventually boil down to what the operating system offers which is almost always https://www.man7.org/linux/man-pages/man2/read.2.html. I've found that learning a bit about the posix C APIs to be helpful since those are the operations every programming runtime eventually boils down to.
Some languages offer higher level APIs on top and some languages even manage not to screw up (but some still do. nodejs 👀).
Thanks, I'll read more about the underlying impl.
Does it offer any advantage to (string/split-lines (slurp "a.txt"))
if I'm just going through line by line with transduce?
Potentially. For small inputs, it doesn't really matter.
For large inputs, using line-seq
+ transduce
would allow you to do garbage collection as you go so that you don't have to fit the full file in memory. The example code you gave with transduce is still combining everything in memory, but if xf
was filtering or some other reduction was happening, than it could be more memory efficient.
Again, for small programs and inputs, it doesn't really matter.
However, here are some general tips that might help for scaling to larger programs and inputs:
• Don't mix lazy sequences with I/O
• Don't use slurp
• Check out with-open
• Check out iteration
• Transducers work great even in cases where there might be I/O or side effects
I think I understood about my example with tranducer with conj not mattering, so something like (transduce xf + ...)
would matter right? some reduction f that doesn't hold onto the head
Yea, but even with (transduce xf conj '() in)
, if xf
was something like (filter (constantly true))
or another transducer that filtered most of the content, then it could matter there too.
Also, another tip is that if you're using transducers to produce a collection, then into
will be shorter and more idiomatic. For example (into '() xf coll)
.
Not that matters, but '()
doesn't need to be quoted. The empty list ()
evaluates to itself since there's nothing to call.