Fork me on GitHub

is there a convenient way to determine which source files get pulled in during a call to (compile my-ns)?


@sogaiu I think this dynamic var might help - the code that loads namespaces uses it to decide whether to print

user=> (doc clojure.core/*loading-verbosely*)
  True while a verbose load is pending


thanks! i'll give that a try


@noisesmith that was helpful, thanks!

Eduardo Mata01:12:35

how could I spit an edn and have it pprinted ?


pprint takes an optional writer arg, or you can use with-out-str to create a string out of what would otherwise be printed, and then write that



(ins)user=> (with-open [w (io/writer "foo.edn")] (pprint {:a 0 :b 1 :c (range 12) :d (zipmap (range 10) (range))} w))
(cmd)user=> (println (slurp "foo.edn"))
{:a 0,
 :b 1,
 :c (0 1 2 3 4 5 6 7 8 9 10 11),
 :d {0 0, 7 7, 1 1, 4 4, 6 6, 3 3, 2 2, 9 9, 5 5, 8 8}}

• edit - removed redundant io/file call that io/writer doesn't need, a writer should use with-open

❤️ 4

with-out-str effectively does the same thing

(ins)user=> (spit "bar.edn" (with-out-str (pprint {:a 0 :b 1 :c (range 12) :d (zipmap (range 10) (range))})))
(ins)user=> (= (slurp "foo.edn") (slurp "bar.edn"))


funny enough, nearly identical character count between the approaches


Didn’t know about the extra output. Thanks!


I wouldn't know it took a writer arg, except for the error you get when you pass two clojure data objects to one pprint call (hey, it works with println...)


the version without the with-open worked accidentally thanks to the writer's finalizer since it fell out of scope instantly, but the correct way is to use with-open, so I fixed it


is there an appropriate channel to announce projects?


#announcements ?

👍 4
Eduardo Mata02:12:48

I have build a jar file. However, when I run it with java -jar I get in return an error telling me that one of my functions does not exists! But it exists. If I run it in the repl, It works 100%

Eduardo Mata02:12:18

Caused by: java.lang.RuntimeException: No such var: elastic/search-hits

Eduardo Mata02:12:15

I can even run my project in the repl directly in the namespace where the exception is coming from and run the function with no problem

Eduardo Mata02:12:17

Eastwood, kibit, yagni, and bikeshed are coming back postive, with no erros


How are you building your uberjar?

Eduardo Mata02:12:27

it is kind of complicated. I am using boot and my own boot task.

Eduardo Mata02:12:37

I just deleted my boot cached and it work 😐


My off the cuff guess is you are calling eval somewhere and assuming that the value of *ns* is something it is not

Eduardo Mata03:12:14

It is weird becasue if I run the jar couple times in the row. the Error will go away


Hi. What is the most common deployment model for clojure web apps (servers)? Specifically, deployments when there are services like AWS ECS Fargate, does one really need Application Servers (containers) like Tomcat, Jetty etc.? Anyone using systemd + jvm + nginx sidecar deployment in production?


I use it. Only it's a single in-house server. 🙂 No clouds here.


I just use a docker image with clojure installed there. we dont have any special configs. you dont benefit of an owner role thats all


Great, thanks. And, with the usual web service (app) involving RDBMS, is PostgreSQL a viable choice for Clojure?


I think it's the perfect choice for about 99% of scenarios. YMMV though.


It has been the primary choice for me and the tools I've used so far. I am just curious, maybe there are some core inconsistencies you may have encountered.


Not really inconsistencies - just an occasional need to map some type that some jdbc library didn't map itself. So far, has happened to me only once. Also, it depends on how you will create your queries. E.g. with honeysql and honeysql-postgres, I sometimes need to add a defmethod that describes some keyword that the libraries don't know about.


Nice. Btw, is Ring the de-facto framework? Can you serve using just stdlib?


I have no idea, I have never used Ring. I use Edge, which uses Yada, which uses Aleph.


Ah, no - I've used Ring once, for my very first Clojure project that was an entry project for some job. 🙂


Not at all.


For the ones coming from ruby, golang, nodejs - java terms and acronyms are just 😱


пойду рыть дальше


Examples of Java acronyms?


jstl, war, eej, servlets, server pages - some of those


To be honest, I only barely know what war means. 😄


The rest of them - no idea. It doesn't prevent me from writing software in Clojure.


i learned it today, it has to be web archive


There are plenty more acronyms and concepts in the JavaEE world. It doesn't mean you need even a single one of them to create something of value.


That confidence you have only after deploying, some production ready apps. But, for the beginners, we try to find the analogous tools and concepts.


So we can map, project our understanding to the new ecosystem.


Or is it just me, not sure.


The best advice out there in this situation is probably "just go do it". 🙂 Not "just deploy something to production" of course, but "just create a working web app and see for yourself". Try Ring, try Aleph, try raw CLJ, see what you like. Read a bit about them, create some more. Yet another kind of loop, not unlike REPL.

👍 4

user=> (Character/isWhitespace (char 65279))

😑 4

From "The static function java.lang.Character.isWhitespace(char ch) correctly recognizes U+00A0, U+180E, U+202F, U+2060, U+FEFF as non-breaking spaces and excludes them from being considered whitespaces according to the documentation and specifications." Not sure why though.


Postgres choked on it when inserting XML: XML declaration allowed only at the start of the document


Ooof, that error still haunts me, although for a different reason.


Hi. I am getting reflections warnings call to method indexOf can't be resolved (target class is unknown) The function params are a regex string and a sequence (vector of strings\n), it's returning index of the first occurrence of sub-string in seq. Is there a way to resolve the warning?

(defn firstindexof [timestap seqq]
           (.indexOf seqq
             (filter #(re-find timestap %) seqq))))


I guess

(defn firstindexof [timestap seqq]
           (.indexOf seqq
             (filter #(re-find timestap %) seqq))))


Not,really( still complaining


I think it doesn't know about the seqq type - try adding a type annotation for it.


it's a sequence of strings, or rather a sequence returned by (line-seq reader). is there a way to annotate it by type?


(type (line-seq ...)) returns clojure.lang.Cons. Try using that. Although I find it strange that the type isn't known here. In what context do you get the reflection warning? I tried it in a REPL and don't see anything.


The warning happens when evaluating it in repl.


your advice helped, thanks!

(defn firstindexof [timestamp ^clojure.lang.Cons seqq]
  (.indexOf seqq
             (filter #(re-find timestamp %) seqq))))


Really interesting. Can you tell how you run your REPL? Because right now, the code will probably fail if you pass there anything but Cons. E.g. a vector.


yep )

Execution error (ClassCastException) at data-health.dataloss/firstindexof (form-init17101450020595890464.clj:1).
class clojure.lang.PersistentVector cannot be cast to class clojure.lang.ASeq (clojure.lang.PersistentVector and clojure.lang.ASeq are in unnamed module of loader 'app')


Ah, you have (set! *warn-on-reflection* true). I didn't know about this option. It seems that you have 3 options: 1. Stop caring about reflection 2. Use a more wide-spread type annotation (e.g. just APersistentVector) and just wrap the argument each time you call the function (in vec) 3. Rethink the way you work with data - maybe there's a more idiomatic approach, as explained e.g. here:


yes, the option on reflection is indeed set, I though you new about it, as your advice was spot on : ). I can choose to ignore it but it's interesting to see how can I solve in a proper way. I was thinking about something generic, like a collection etc that will accept set, vector, and list type


The issue is that all of the collections that implement .indexOf, implement it on its own and not as a part of some interface.


In JavaScript I can do text.replace(regExp, (m, grp) => grp.toUpperCase()) How can I replicate it in Clojure? The thing is that my replacements aren't static, I need to run a fn on the match. I could do it in two steps - 1) extract all matches, 2) create a map match -> replacement, 3) replace every match by the corresponding replacement one by one. But perhaps there is a nicer way?


Some of the clojure string functions take a function


Replace does, so you could use that?

Daniel Stephens13:12:43

(clojure.string/replace "some-text" #"some-regex" clojure.string/upper-case)


Awesome, how could I have overlooked that? Thanks a lot!


When shutdown-agents is called in Clojure, it stops both the agent threadpools (`soloExecutor` and pooledExecutor) but since future spawning happens on the soloExecutor, is there any way to say that I want the agents to stop but new futures can still be spawned? Without using something like a dedicated pool and spawning futures on it like with


Would it be possible/useful to shutdown just the pooledExecutor? (i.e. (.shutdown clojure.lang.Agent/pooledExecutor))


you should only call shutdown-agents if you are shutting down the jvm


@U1UQEM078 Thanks, I think that would work, I’ll try it out @U064X3EF3 I am calling shutdown-agents during JVM shutdown but there are a few other shutdown hooks that are causing the JVM to take more time to exit, and in the meantime, if some thread calls future, it gets rejected. I’m right now catching the rejected exception and running it in the calling thread.


What is the most Clojure-friendly observability platform? (New Relic, Honeycomb, LightStep, etc.)


Let me know when you find out. We basically use which is to say we decorate fns manually for newrelic's sake


Hadn't seen that before @U0MQW27QB -- nice! We rolled our our tracing with New Relic (I blogged about it years ago) but this is much nicer. @U0HJJF9A4 Happy to answer Qs about New Relic -- we've been using it for years.


I certainly know of people doing both New Relic and Honeycomb with Clojure /cc @ghadi


(require '[clj-time.format :as f])
(def example-date "Sat, 02 Nov 2019 00:00:00 GMT")
(f/parse (f/formatter :rfc822) example-date) ;; malformed at GMT
is this a bug or it this date truly not rfc822?


There is no joda time formatter symbol that corresponds to the timezones allowed in a rfc822 date


Thanks. I'll try


I must the the author of has courage. He uses clojure in the library name and the core namespace is just "java-time"


single segmented


Love that lib, hate that name/namespace 🙂

Ramon Rios17:12:31

Anyone familiar with Schema?


Probably, and there's also #schema

Ramon Rios17:12:36

I'll ask there. Thanks.

Eduardo Mata18:12:07

If I start a Thread such as (-> (Thread. function-name-here) (.start)) How could I stop it?


(let [thread (doto (Thread. fn)  (.start))]
(.interrupt thread))


i find myself reaching for doto more often than -> for java interop

Eduardo Mata18:12:15

yeah, I will probably do the same to avoid kibit linting yelling at me about this


NB: the interrupt method doesn't stop a thread, it sets a flag that makes certain methods exit. This is cooperative and opt-in, and you should make sure any thread that needs to be interruptable calls a method that exits cleanly if the interrupted flag is set


there's no way to safely stop a thread from the outside in the jvm, it's always voluntary


Is there a way to generate all valid values for a spec?


no. (s/keys) is a spec that describes any map with any keys


"all"? That could be an infinitely large set of values...


You could use s/exercise to randomly generate as many valid values as you want tho'...


Ah all is difficult because spec cannot be that smart


Trying to solve Advent of Code day 4 using spec


• It is a six-digit number. • The value is within the range given in your puzzle input. • Two adjacent digits are the same (like 22 in 1_22_345). • Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679).


How many possible


sounds like you want logic programming - give constraints and the code returns some datum satisfying the constraints


since you need every possible solution (or the count...), you might think about the most efficient way to generate unique numbers fitting the pattern


Ah yes it’s logic programming.


Although now you can generate it more smarter than a core.logic evaluator I guess


I did that one in core logic if you’d like to compare when you’re done


Don’t know if it’s idiomatic though


I’ll check afterwards in #adventofcode 🙂


Is it possible to update a value in an atom, by it's index? For example changing the value of the 5th value in a list


ignore the atom. its just a container. if you know how to update the 5th value in a list you can do it in an atom


but it has to be an atom for me to be able to update it, right?


if you want to update a single reference, it needs to be some kind of mutable container. Not sure if that's your requirement though.


Yea I think that is what I want yea


An atom is a mutable container/box/pointer/reference, intended to point at an immutable value. Creating a new immutable value from an existing immutable value, you have most of the Clojure library to help you with, and is no different than starting with any immutable value and producing another one.


If the immutable value is inside of an atom, then the only way to change what immutable value the atom points to, is via a function for modifying an atom, typically swap!


if you're new to functional programming a common pitfall is to think you need mutability and atoms much more than you might otherwise need. Not saying that's your case now but that's something to be aware of if you're a beginner (and apologies if you aren't.)


@olle142 you can create a new list with a new value at the 5th index by using assoc:

(assoc '(0 1 2 3 4 5 6) 4 10)
;; => '(0 1 2 3 10 5 6)


user=> (assoc '(0 1 2 3 4 5 6) 4 10)
Execution error (ClassCastException) at user/eval293 (REPL:1).
clojure.lang.PersistentList cannot be cast to clojure.lang.Associative


you must have been thinking of square brackets here?


yeah I made that comment below, was thinking of vectors


if you want to update an atom that contains the list, you can use swap!


that is not correct, you cannot do that in clojure


maybe I’m thinking of vectors. on mobile atm


@dpsutton Yea I'm not quite used to the immutable way of thinking yet. If I need to update a lot of items in a list, is it more efficient to use an atom or is it better to create new lists for it? (because that's how you want to do it in clojure, right?)


Really? I will try that out.


I don't have to use a list, I can make it into a vector instead if that's the case


it will create a new immutable data structure either way, @olle142. whether you use an atom or not


this is usually pretty efficient due to the way that the immutable data structures are implemented


Alright, then I should probably just do it that way instead.


see Structural Sharing


I only really "need" atoms for state and stuff usually?


I haven't provided a solution for you because there's a lot that can vary according to your requirements and assumptions. ie, what if there are fewer than 5 elements, what data type, how its used, etc


also #beginners is a great place to hash these things out as you're getting used to the functional/immutable paradigm


Trying to use the assoc function on my list gives me a ClassCastException, which has to do with trying to redefine my constant or something?


lists aren't associative. the suggestion above was incorrect. vectors are though


in: there is this bit:

If the form being eval‘d is not a “def” of some kind, it’s wrapped in a zero-arity fn and that fn is invoked. I don’t know why that’s necessary. (If you do, please let me know.)
i've been puzzling over this too. does anyone know why this wrapping is necessary? (i think this bit is not explained in clojure pills 17 either.)


@sogaiu Because each expression (at the top-level) is compiled to a class -- because that's the unit of compilation on the JVM -- as if it were an anonymous function definition and then that (compiled) function-as-class is invoked. (my understanding)


(each function is compiled to a class with static invoke methods)


thanks for the response -- will need to study more to understand your answer 🙂


There are probably under 10 people in the world who know the answer to that question off the top of their head, and unfortunately I am not one of them 🙂 This channel and #clojure-dev are the most reasonable places to ask, so you are in the right place -- it all depends on whether one of those few people happen to be reading.


"necessary" might be too strong a word in your question "why this wrapping is necessary", i.e. likely the code could have been implemented differently. It may be that it makes the compiler more straightforward to reduce the number of kinds of 'top level' forms.


Also, feel free to delete the code that does that wrapping, compile your custom version of Clojure locally with a different version number, and try it out on a Clojure project of yours and see what happens 🙂 Sometimes that is a quicker way to find an answer.


thanks a lot for the feedback and tips -- i guess i should become more familiar with building a custom clojure version 🙂 may be an early version would be easier to get working -- one that doesn't involve spec.


Happy to walk you through the steps if you are interested. It is pretty quick and easy once you know how.


i'll give it an attempt or three 🙂


You should already have Java installed. Install Maven, then from the root of a Clojure source tree, type mvn clean install , and if it succeeds, then near the end of the output it should have a line like the one in my next message. Use the version number there in your org.clojure/clojure dependency version number instead of "1.10.1", e.g. replace it with "1.11.0-master-SNAPSHOT", and run your Clojure code again. It will look in your $HOME/.m2 directory for that locally installed version, as it does for any other version of Clojure that is first downloaded from the Internet and then put into your $HOME/.m2 directory.


[INFO] Installing /Users/andy/clj/clojure/target/clojure-1.11.0-master-SNAPSHOT-sources.jar to /Users/andy/.m2/repository/org/clojure/clojure/1.11.0-master-SNAPSHOT/clojure-1.11.0-master-SNAPSHOT-sources.jar


If you do not want to run Clojure's built-in tests for some reason (e.g. you made only a tiny change and expect them to pass), you can skip those by instead using mvn -Dmaven.test.skip=true clean install


Just think of all the places in the Clojure compiler Java code you could stick in a little System.out.println(...) call and learn all kinds of things 🙂


it seems to be working (including my first System.out.println 🙂 ). i was under the impression that there was some kind of extra work involved because of some kind of circular dependency(?) with spec. perhaps that is just a misunderstanding on my part? in any case, thanks for the fishing pole 🎣


It's even more interesting to set a breakpoint in the compiler and step through the process


yes, i've been doing that on and off using cursive, but i have found it to be unstable on occasion -- it's fantastic when it works though! i've found it's harder / cumbersome to make significant behavioral changes using a debugger though