Fork me on GitHub

Anyone know of a good drop-in replacement for the standard GraphiQL GUI that parses EDN? I'm sure I could toss something together with ClojureScript, but figured I'd ask.


Is there a more concise way to write this function? (filter #(if (some? (second %)) %) {:foo nil :bar 89})


(filter (comp not nil? val) ...)


Better to use some? instead of not nil?


But, yes, better to use val than second when dealing with map entries.


@U010Z4Y1J4Q This really feels like a question that is better suited to the #beginners channel where people have opted-in to help with basic questions like this...


Ah, some? ... I didn't remember it. Yes, this would be cleaner: (filter (comp some? val) ...)


@U051MHSEK The OP mentioned it in their question.


I misread it as some and that just shows me what happens if I haven't written Clojure in a while ¯\(ツ)


And another reason why questions like this belong in #beginners rather than #clojure ...

👍 4

@U010Z4Y1J4Q I've added you (back) to the #beginners channel.


I wonder if #beginners is misnamed.


It’s an attribute of the questioner, not the question.


Happy to discuss potential renaming in #community-development but we try to rename channels only very occasionally (since channel names are often documented out in the wild and it's confusing if someone comes here and those documented channels no longer exist).


Makes sense!


Basically what I want is to return a map that contains only the key value pairs that are non-nil {:bar 89}. It doesn't have to a list of vectors of key-value pairs ([:bar 89]) as in the result of the above example.


I have this following idiom in my code:

(deftest my-test
       (is (= 1 2)) ;; etc.
And it seems like a good idea to create a macro which would replicate this like so:
(deftest-sync my-test
   (is (= 1 2))
And I have tried this:
(defmacro deftest-sync [name test]
  `(deftest ~name ~(run-test-sync ~test))
But on doing :
(macroexpand '(deftest-sync some-test (is (= 1 1))))
I simply get the result:
(deftest-sync some-test (is (= 1 1)))
What am I doing wrong?

Ben Sless07:04:56

You unquoted twice, you don't want to unquote the entirety of the run-test-sync. Should probably be

(defmacro deftest-sync [name test]
  `(deftest ~name (run-test-sync ~test)))
(note the missing tilde)


That still gives (deftest-sync some-test (is (= 1 1))) on macroexpand

Ben Sless07:04:01

Are you sure? I just tried this in the repl:

user=> (defmacro deftest-sync [name test]
  #_=>   `(deftest ~name (run-test-sync ~test)))
user=> (macroexpand '(deftest-sync some-test (is (= 1 1))))
(user/deftest some-test (user/run-test-sync (is (= 1 1))))


yeah, I'm sure. Could it be because it's a cljs repl?

Ben Sless07:04:18

I wouldn't know, never worked with cljs


Yeah it's working in the clojure repl but not in the clojurescript repl


bug in the repl or in cljs itself?


actually it woks now


However, the macro doest seem correct


(deftest my-test (run-test-sync (is (= 1 1)) (is (= 2 1)) ) ) evaluates to #'mytest


But (deftest-sync my-test    (is (= 1 1))    (is (= 2 1))       ) evaluates to (deftest nil nil)


can someone explain me the reason having definterface and deftype inside a do in the repl won't work? i have to deal with a macro that generates something like (numbers all gensyms)

 (def foo)
  (definterface G__49771 (invoke [G__49772]))
  (deftype foo49770 []
   (invoke [_ G__49772]
     (let [bar G__49772] bar))))
  [G__49769 (new foo49770)]
  (defn foo {}
     (.invoke G__49769 G__49773)))))
this dies on the repl at deftype saying,
Syntax error compiling deftype* at (/tmp/form-init6201477943960772507.clj:7:3).
Unable to resolve symbol: G__49771 in this context
it works if i compile/run the code. i can also get it to work manually in the repl if i remove the dos. how could i get this to work in the repl?


it works here on the repl


which repl are you using?


if you're using some fancy repl that wraps input commands somehow, that would explain it


as it would prevent the unwrapping of do that clojure does for toplevel dos


i was starting a headless lein repl and connect to it from atom with clojure party repl


and indeed, going directly into a lein repl, it really does work


ok, I don't know what that is but it sounds like this is what's happening


thanks! it sure is...


gonna debug this more and try filing a bug report with the plugin


everyone on the team uses the same setup so we were all getting the same errors...


thanks again!


a minimal repro should be just (do (deftype A []) A) FWIW

💯 4
Michael J Dorian14:04:57

Hey friends, I've got a plan to tackle a problem but I'd like to have a better plan, if one exists. I've got a string, and the string represents clojure code. I need to remove all the line endings from this string, without altering the compiled value of it. It will always be a hashmap, starting with { and ending with }. I would just do (str/replace string #"\n" ""), but that breaks when the map contains ;comments, and alters the value of string literals So what I'm thinking of doing is making a loop that loops over each char in the string and removes newlines UNLESS they terminate a ;comment, OR if they're inside a string literal. Ofcourse ;comments don't count if they're in a string literal, and string literals can't start inside a comment. Is this a good plan? It feels like a not-great plan, but I'm stumped for other options. Thanks!!


Is it important to preserve the comments?

Michael J Dorian14:04:17

Yes, unfortunately. I'm doing some code formatting, and I wasn't able to remove newlines with rerwite-clj


@doby162 I'd use parcera


You can match whitespace nodes, and remove newlines from the string in them.


You may need to match the comments too, I can't remember if the ast distinguished or not, but it'll make it easier for sure.

Michael J Dorian14:04:18

Well, thanks! I'll give this a try. Also, if anyone happens to know that this Should have actually been easy with rewrite-clj, let me know! It seems to skip whitespace, so far as I can tell


There's definitely some way to get rewrite to do this, but I think parcera is more ergonomic.

Michael J Dorian14:04:41

simple_smile thanks a bunch, I had a feeling plan-a wasn't going to be the best


if you have a string with clojure forms in it, consider reading the forms, then prning them to a file, then running a source code formatter on the file


reading as in clojure.core/read

Michael J Dorian15:04:46

Ah, a code formatter is what I'm trying to do!


Yeah, clojure core doesn't have a good facility for that due to dropping comments


I wrote my code formatter with parcera and enjoyed it

👍 4
👀 4

Out of curiousity I just too a look at parcera, I'm curious about this line: Seems like this will parse odd "inputs" without an issue whereas maps should be key-value pairs, am I right? I don't have experience with antlr.

Michael J Dorian15:04:23

Luckily in my case I'm not responsible for the correctness of inputs... I just need to not break the code 😁

Michael J Dorian15:04:41

rewrite-clj will object if you attempt to make a hashmap with an odd number of forms though


Yeah, right. I'm asking especially because I took the tools.reader wrapper path in a current side project especially because I needed something like '{' input* '}' inside maps and neither tools.reader nor rewrite-clj allowed it. I overlooked antlr as too complex but looking at parcera I feel like stealing the g4 file would work and allow me to remove 80% of my code...

parrot 4
Ramon Rios16:04:45

"CREATE TABLE test_table (some_column varchar(255), oth
er_column varchar(255) CONSTRAINT constraint_name UNIQUE KEY (`some_column`,`other_column`))"
"CREATE TABLE `test_table` (`some_column` VARCHAR(255),
 `other_column` VARCHAR(255)) CONSTRAINT `constraint_name` UNIQUE KEY (`some_column`, `other_column`)"
Folks, i'm trying to add the constraint statement inside the parentheses, intead of have ou of it, as have in expected. Do you folks have any insight of how can i do it?

Ramon Rios16:04:37

(let [base-sql (str "CONSTRAINT " (ddl/escape-identifier ddl name))
        cons-sql (clojure.string/join ", " (map #(ddl/escape-identifier ddl % ) columns))]
    (str base-sql " " type " (" cons-sql ")"))
That's the current code i did for it.


If it's an option, I'd suggest looking at HugSQL - it has built in ways of passing identifiers etc

Ramon Rios16:04:20

We already use another implementation. Once i'm expanding a existent library, probably not going work on it now. But thanks for the suggestion

Ramon Rios16:04:59

(defn join-string 
  [query specs]
  (let [count (-> (count query) (- 1))] 
      (-> (subs query 0 count)
          (str " " specs ")"))))
Found a way to do this. Hope it's not a McGayver solution


using count to bind something called count is a bit odd


perhaps (let [length (dec (count query))] ...) or (-> query count dec)or whatever


is there a nice and friendly way in clojure to convert from scientific notation 1.87E+5 to 187000.0 ? i really want the bigint 187000 .. but any longer version will do

Alex Miller (Clojure team)17:04:47

both are different representations of the same number

Alex Miller (Clojure team)17:04:11

there are ample formatting options for converting from a number to a string in the jdk


i will check java formatter then

Alex Miller (Clojure team)17:04:42

full spec is at and this is supported in the clojure format function

Darin Douglass17:04:42

user> (Float/parseFloat "1.87E+5")

Alex Miller (Clojure team)17:04:39

you should typically prefer Double/parseDouble over Float/parseFloat

👍 4

will check out that Double/parseDouble


same answer .. but what is reason to prefer Double ?

Alex Miller (Clojure team)17:04:08

Clojure decimals are always doubles - Clojure doesn't support java floats


gotcha .. good to know

Alex Miller (Clojure team)17:04:05

single precision floats are pretty bad, really only useful if you want something where you are ok with bad precision and trying to shave heap memory


whao .. that was far too easy. thanks mate 🙂

Alex Miller (Clojure team)17:04:46

there is also a function to make a bigint

Alex Miller (Clojure team)17:04:47

user=> (bigint 1.87E+5)

Alex Miller (Clojure team)17:04:03

it's unclear to me what the type of either your input or desired output is


gotcha .. yeah .. i need the bigint .. so that one is nice too .. either way .. i have my answer with 2 good ideas


@abrooks re your question about geo from a while back, happy to answer any questions you have. i just made a new channel called #gis if that’s a useful place to organize conversations — not sure what else is important to do in terms of channel management, or if it’s better to try to encourage discussion on zulip or another platform instead


development on factual/geo has been pretty limited recently, though i am trying to get it working with cljs now that bundle support is there. i’ve also been working on and off on willcohen/ovid and willcohen/aurelius as libraries that build on top of factual/geo and try to streamline what i do day-to-day with GIS, though as you can see they’re basically still undocumented and haven’t even hit a first release

Alan Thompson19:04:20

Excellent series of videos by Uncle Bob Martin:


They don't belong in #clojure but feel free to post them to #news-and-articles (or #off-topic since they aren't Clojure-related, right?)


Hi. What's a more concise way to call (not zero?), this feels too verbose:

(filter (every-pred number? #(not (zero? %)) odd?  #(< % 7)) [0 1 0 2 5 9 0 3 0 4 -1 -2 :a {} ])


(complement zero?)


not more concise i guess


nope, that's even longer : )


though I am wondering why (complement zero?) works in the filter as is and (not zero?) needs to be wrapped in an anon. function..


complement returns a function, not returns a value


yep, i guessed it's some of this kind of magic 🙂


@U11BV7MTK (complement zero?) wins, there are fewer brackets and therefore it's more readable and less thinking 'wtf had I written a year?' ago : }. thanks


sometimes I wish things like partial, complement, comp all had shorter names


eg. complement could be ~ or even !


Oh I really like that


(def not-zero?
  (into #{}
        (remove zero?)
        (range Long/MIN_VALUE

trollface 8

@U051SS2EU I wished for the shorter names as well, especially to use in (comp) and settled on (def pa partial)


well you can just def that to something more concise


#(not= % 0)


you shouldn't use = to check for 0, at least one should use ==, and zero? exists for a reason


Quick interop/reflection question: If you have a (Java) object and you know it has a .close method but it does not have a predictable base class or interface you can use as a type hint, is there a way to call the (unique, no-arg) .close method without triggering a reflection warning from (set! *warn-on-reflection* true)?


The concrete situation here is that HikariCP and c3p0 both provide connection pooled datasource objects and both have .close methods but their datasource types have nothing in common that has a .close method -- c3p0 has its own PooledDataSource class that implements .close (and that in turn extends javax.sql.DataSource) where HikariCP implements .Closeable (which has .close in it).


I'm happy to do actual runtime reflection to find and call the .close method, as long as it avoids Clojure's reflection warning (but I'm looking for some guidance on the simplest code to achieve that).


in the past I've used a dispatch to ensure there was only one code-path for each type, eg. you could have a multimethod or protocol where the implementations would look the same except the type hint


it might be overly precious to use a macro for this, if it's not a repeating pattern you could even use cond


The set of possible input classes is actually open-ended in this case.


I have some reflection code that works but it's ugly 🙂


in that case you could use a protocol or multimethod and extend it to each thing, clojure won't complain about runtime protocol dispatch


Where they mention the current solutions are multi-methods, protocols or instance? checks


yeah, since this is open and not statically knowable, protocol or multimethod actually fit here IMHO


No, this has to be self-contained and require no extension by users.


So far

(defn- attempt-close
  "Given an arbitrary object that almost certainly supports a `.close`
  method that takes no arguments and returns `void`, try to find it
  and call it."
  (let [^Class clazz (class obj)
        ^java.lang.reflect.Method close
        (->> (.getMethods clazz)
             (filter (fn [^java.lang.reflect.Method m]
                       (and (= "close" (.getName m))
                            (empty? (.getParameterTypes m))
                            (= "void" (.getName (.getReturnType m))))))
    (when close
      (.invoke close obj (object-array [])))))


That avoids reflection warnings from the compiler and calls the first 0-arity .close method it can find that returns void.


It's so next.jdbc can support Stuart Sierra's Component library without needing it as a dependency in a nice, generic way:

(defn component
  "Takes the same arguments as `->pool` but returns an entity compatible
  with Stuart Sierra's Component: when `com.stuartsierra.component/start`
  is called on it, it builds a connection pooled datasource, and returns
  an entity that can either be invoked as a function with no arguments
  to return that datasource, or can have `com.stuartsierra.component/stop`
  called on it to shutdown the datasource (and return a new startable
  [clazz db-spec]
  (with-meta {}
     (fn [_]
       (let [pool (->pool clazz db-spec)]
         (with-meta (fn ^DataSource [] pool)
            (fn [_]
              (attempt-close pool)
              (component clazz db-spec))})))}))


what about an instance? check that special cases c3p0 (grandfathers it in) and demands all other inputs be ?

👍 4

(def ds (component/start (next.jdbc.connection/component CPDSClass {:dbtype "..." :dbname "..." ...})))
(next.jdbc/execute! (ds) ["select ..."])
(component/stop ds)


I don't know that you can rely on arbitrary connection pooling libraries implementing .Closable and next.jdbc cannot introduce a direct dependency on a specific one (such as c3p0).


The joys of writing dependency-free libraries that can behave generically... 🙂

🙂 4

Hum... What about letting the user provide the type hint?


There's something about hidden reflection in a library dependency that seems dirty to me.


Making a GraalVM build will require a big deep dive now for example.


Like what if component let you pass in the close function?


Horrible usability.


(although I suppose I could default the close-fn to (fn [^.Closeable ds] (.close ds)) and force poor old c3p0 users to override it... not that HIkariCP doesn't also have its own weirdness)


or default it to (memfn close)which silently reflects I was wrong, it does reflect


I wouldn't be surprised if there are other things that prevented GraalVM binaries to be produced from next.jdbc programs already -- Borkdude is working on JDBC support in Babashka and, so far, has only managed to get PostgreSQL supported -- both MySQL and SQLite seem somewhat incompatible with Graal...


Can you just set warn on reflection false above it and then reenable afterwards?


@U051SS2EU Oh really? Interesting... let me try that...


((memfn close) pool) produces a reflection warning @U051SS2EU


yeah - sorry I did edit above


@U11BV7MTK That sounds... deliciously horrible...

😂 4

Maybe just keep the warning?


What's the big deal? I mean, if you are doing reflection, why not be explicit about it if the user cares to know.


@U0K064KQV for folks who set reflection warnings on for their whole build, why should they have to suffer my code producing a warning? Folks create GitHub issues about that sort of stuff. No, just no.


@U11BV7MTK That certainly does hide the reflection warning but a) that feels like cheating and b) that's still going to trip anyone who uses Graal, right?


gh issue "this code reflects" response "get rid of reflection by providing this arg / extending this multimethod"


I mean I get it, but I'm not a fan of circumventing the warning either. If I set warn-on-reflection it's because I want to know if reflection is happening anywhere in the code, libraries included


Right, and it's important to me that my library is "clean" in that respect.


Well it seems in line with your intention that you are open to reflection. It’s not a warning it’s intentional


With respect to not be doing reflection? Or not warning about doing it?


Could graal people use this regardless of the warning? The reflection will kill them not the warning


It's probably irrelevant in this case, so it might be the right trade off, but what if I was calling component in a hot loop? I know what doesn't sound realistic, but I'm just trying to explain why I kind of don't like it if my dependencies secretly try to hide important aspects from me.


actually connecting to a db is so much slower than reflecting on a method though


My personal vote would be, leave the warning, but have a mechanism where the user can get rid of it by say providing the close function or a type hint.


If using java.lang.reflect kills Graal then it's a non-starter too... which is moving me closer to @U0K064KQV’s suggesting of optionally passing in the close function at this point


(and defaulting it to the .Closeable version)


that means you get a runtime crash when the hint doesn't match the impl coming in


Actually, you can use java.lang.reflect, but you need to tell Graal which class needs reflecting over


unless you protect it in a conditional branch with an instance? check I guess


So if you document it properly it might be fine as well.


I thought they were hints, because if Clojure compiler doesn't actually find the method on the type it defaulted back to Object?


Though I guess there is the weird case of a connection pooling library that wouldn't have a .close method at all?



(ins)user=> (def hinted #(.close ^.Closeable %))
(ins)user=> (defprotocol Distance (close [this]) (far [this]))
(ins)user=> (hinted (reify Distance (close [this] true)))
Execution error (ClassCastException) at user/hinted (REPL:1).
class user$eval202$reify__203 cannot be cast to class .Closeable (user$eval202$reify__203 is in unnamed module of loader clojure.lang.DynamicClassLoader @50a3d0f6; .Closeable is in module java.base of loader 'bootstrap')


once you hint, the method is specialized on the class, and other methods with the same signature but different class with crash


I discovered this the hard way implementing a setUncaughtExceptionHandler for a kafka stream (that just happened to accept the same types / args as Thread.setUncaughtExceptionHandler without inheriting Thread)


Yeah, that's an interesting usability question @U051SS2EU...


Interesting, didn't know that.


Thinking about this some more, next.jdbc uses for the connection pooling stuff which is full of explicit Java reflection stuff... So I'm worrying too much about this since ->pool already depends on the java.lang.reflect stuff!


So I've gone back to this

(if (isa? clazz .Closeable)
                (.close ^.Closeable pool)
                (attempt-close pool))
where attempt-close is the java.lang.reflect-based thing above.


Thank you everyone for your input on this. I guess allowing users to pass in their own close-fn might also be worthwhile just to deal with connection pooling libraries that don't even have a .close function...


there's also this if you don't otherwise need to extract the class

(instance? java.lang.CharSequence "hi")
(which becomes Closeable/ pool of course)


the rest of clojure is so unbelievably consistent, the difference between isa? and instance? arg order sticks out


Yeah, it caught me out when I tried it half an hour ago -- the way next.jdbc.connection/->pool works is that it already takes a Class so I'm using that to provide the default close-fn before creating the pool instance.


extension via metadata to not depend on the component lib. Cool!


It all started as yak shaving due to Jacob O'Bryant's announcement of his Component alternative which inspired me to remove a record from a Component at work and then I started thinking about next.jdbc 🙂

👍 4

wrap the call in a protocol? does that work?


I suggested that or multimethod in the thread above, I don't think he liked the idea