Fork me on GitHub

Tools deps talks about a "basis" - i can infer somewhat that it means "run in the context of this deps.edn", but what exactly is a basis?


Yep both of these answer the question


Did I miss where that is explained?


(def basis (b/create-basis {:project "deps.edn"}))
what's the outcome when you run this


Interesting discovery this morning. I wrote a implementation of a sorted set that behaves slightly different than a regular sorted set. It allows for elements deemed equal by compareTo to reside in the set. This breaks assumptions made by subseq and rsubseq. When the test is one of #{> >=} for subseq, and the first element from the seqFrom call is not included, subseq will just return (next s), which does not hold for this data structure. It would follow that subseq and rsubseq assume that the sorted collection follows Background reference:



(def sm
    (sorted-multiset-by #(compare (:k %1) (:k %2))
      {:k 0
       :v "a"}
      {:k 1
       :v "b"}
      {:k 1
       :v "c"}
      {:k 0
       :v "c"}))
=> #'com.computesoftware.sorted-multiset/sm
(subseq sm > {:k 0})
=> ({:k 0, :v "c"} {:k 1, :v "b"} {:k 1, :v "c"})


Why does clojure not support java number format for in literals? Eg why is 0b1101001001101001_10010100_10010010 a syntax error? (from ) When I have to work with big numbers (6 gigabytes etc) I find it helpful to be able to separate thousands by _.


I was going to suggest Long/parseLong but it doesn't accept the _ syntax either


That feature was introduced to Java way after Clojure had launched.


But also, I don't think Clojure follows precisely Java's number syntax.


There might be a request for it in you can upvote, and if not, you could make one


In the meantime, the best you can do is a data reader literal which takes a string and returns your number: #num "0b11010010_01101001_10010100_10010010" You might even be able to pull it off with a symbol so it could look like: #num 0b11010010_01101001_10010100_10010010 But I think for that it would need to not start with a number not sure

Jeff Evans16:09:56

Does there exist a tool similar to but for Clojure packages? To quantify the public API difference between two versions of a repo/packaged jars/etc.? I haven’t tried jardiff, but I’m just assuming it wouldn’t work because the generated Java class files could have different names across builds (even if nothing changed).


@U04V15CAJ has something in this area


Just take that as an example of how you can write this based on the clj-kondo analysis data


And tweak it to your likings

Jeff Evans16:09:56

amazing. thank you!

Jeff Evans18:09:49

do you know offhand if this detects something becoming :deprecated ?


I mean, clj-kondo supports it. The script currently doesn't look at it.


I think I'm going to rewrite this as a -Ttool thing


and then support it

👍 1
Jeff Evans18:09:02

awesome, thanks. will keep an eye out. and in the meantime, will use the adapted version of your script.


From a CLI perspective, I don't think having to quote the versions like this is neat:

clojure -X borkdude.api-diff/api-diff :lib clj-kondo/clj-kondo :v2 '"2021.09.15"' :v1 '"2021.09.25"'


but I don't think there is a solution for this. -Ttool doesn't really support *command-line-args* right?


I'll just add -main fn as well

Jeff Evans21:09:55

(and (gentleman? :borkdude) (scholar? :borkdude))
=> true

😆 1
Jeff Evans21:09:13

are you open to a PR that allows local file paths for the “versions”? the stuff I want to compare doesn’t get published to Maven

Jeff Evans21:09:05

maybe I will wait until tomorrow to get 1/4 of a Hacktoberfest t-shirt


@U0183EZCD0D I added :path1 and :path2 options for comparing directories or files. The tool now also checks deprecations.


I wanted to get the tests sorted before receiving/adding more features, but I'm sure you can come up with some other ones for Hacktober ;)


Do you have real use case example for tap>? I am trying to figure out when to use it.


Works really good together with Reveal.

☝️ 1

unfortunately I don’t know this one

Ben Sless17:09:41

Which editor are you using?


The first result when I google "clojure reveal". ;)

👍 1

I found it in google too, but I mean I don’t feel how it “Works really good together”

Ben Sless17:09:59

tap sends the tapped values to all sinks. Reveal is one of those sinks. You get a trace of all the values during execution, then you can process and view them in the reveal window

Ben Sless17:09:41

It's way more convenient than attaching a debugger, especially in cursive, even more so when working in a multi-threaded context


well sorry, I still not get it :thinking_face: I see examples like

(def debug-a (atom nil))
(add-tap #(reset! debug-a %))
but what is the point. I can do it without tap.


Probably I misunderstood something very hardly


Taps don't do anything you couldn't have done without them. Just like into, or reduce, or many other things. It's just a nice convenience.


or (add-tap (bound-fn* clojure.pprint/pprint)) While I have to add tap> value I can add pprint in this line


But while they are added there has to be some value which I don’t understand 😉


Three main points of convenience: • No need to import anything • There can be multiple taps • It's thread-safe

👍 1

Supposedly you could leave tap> everywhere with not significant cost, and adapt to needs. Example: in dev you can have some inspector like Reaveal, while in prod in can send that info to a logger or other instrumentation. Not sure how much people does that in practice

👍 1

Oh it makes more sense then. I usually use integrant and log level for such purpose.


*integrant - to load code which change logging


another valid option is to leave tap> in the code, and only call add-tap in dev / staging


where the things that should log in prod can just be log calls


another convenience during dev: being able to remove a println tap and add a swap! tap when you want the data to play with, then changing back to println


yes, you can always just add (prn calls (which is mostly what i do) but tap> allows you to send that to things that aren't stdout... for example your editor might collect them in some other window, or when using something like shadow-cljs they will show up in the browser ui


the default for shadow-cljs is the browser ui, which my teammates use, but since i'm a vim person i usually (add-tap prn) so that anything that is tapped also just shows up in my conjure (repl output) window


and i can call that from my repl connection without having to change the code


I've used tap> very heavily in dev, initially with Cognitect's REBL, then Reveal (linked above), and now with Portal -- -- which I've switched over to recently. These are great tools for visualizing and navigating your data, and they work by add-tap'ing themselves so that anything you tap> appears in them to be viewed/explored at will.

👀 2

Can you share in a few words what prompted you to switch from Reveal to Portal?


And we've left tap> calls in production code because it's "safe" to do so -- and sometimes useful if you need to debug a problem in production (and have a REPL running in your process -- as we do with Socket REPLs).


@U2FRKM4TW With Vlad creating a Pro version (with a bunch of features I don't need) in addition to the standard Free/OSS version, I decided to revisit Portal. I had initially tried both Portal and Reveal and didn't care much for Portal, but it has improved dramatically since I last tried it and I'm liking it a lot. In addition, @U1G869VNV is working on a VS Code extension that would let me run Portal directly in my editor, instead of needing an external browser window open alongside my editor.


In general, I re-evaluate my dev tools once or twice a year, so I'm often switching from one setup to another.


Sounds interesting, thanks!


With my dot-clojure file and aliases, I can easily switch between Reveal and Portal -- or even run both of them at the same time.


@U0WL6FA77 There are #portal and #reveal channels, if you want to try out those tools with tap> (and there's a #rebl channel but I don't think it's very active these days).


@U04V70XH6 that's valuable feedback (it's reinforcing my belief that I should not consider making PRO versions of my tools but rather trust that a sufficient amount of people will sponsor if they would like to see those tools be maintained)

Joshua Suskalo18:09:52

The other value to tap> that I don't think has been mentioned yet explicitly is that you can have multiple taps added (including dynamically) without needing a code change or to re-evaluate anything.


@U04V15CAJ I'm sure the Reveal Pro features are going to be just "killer" for some segment of the user base but they're solving problems I don't have right now. And having free/pro versions always makes me wary that the free version won't get as much love in terms of new features which in turn would make me wary of sponsoring someone for the free version...


@U5NCUG8NR Yup, that's why I mentioned that you can run Reveal and Portal and REBL and they can all be independent listeners for tap>'d data 🙂

Joshua Suskalo20:09:06

Yeah, I think borkdude was saying that sponsor in lieu of a pro version so that there's no appearance of the free version being unloved


> And having free/pro versions always makes me wary that the free version won't get as much love in terms of new features which in turn would make me wary of sponsoring someone for the free version This is exactly my concern when I would introduce PRO versions: that this will "eat" from the group of people who would have sponsored me anyway with a net negative outcome (both financially and in terms of accessibility)


To clarify: I am not against PRO versions or closed source software, there are good reasons for it and I don't want to step on anyones toes... But what Sean said happened to resonate with me.

👍 2

Indeed. And REBL is a good example there: closed source and, for a while, $3/month via Patreon to use it (although it was somewhat on the honor system since you could stop paying and just continue to use the version you had with no future updates).


I think, for a lot of OSS developers, the amount you get via sponsorship is very low (to non-existent), so I can definitely see why someone would hope to boost compensation by adding paid-only features.


Until Cognitect/Nubank started sponsoring folks, I'd never gotten a penny for all my OSS work -- dating back to the early '90s! 🙂


I'm amazed how well the Clojure OSS has managed to compensate people, even if its still a fraction of what a real job would do.


I think I wouldn't mind a "PRO", if the code is all OSS and usable and "PRO" is just like a subscription for paid support. Which I think is kind of what you have done borkdude, with like if someone is sponsoring you you might look into their issues quicker. But when you move some stuff into closed source, your stuff needs to be so good that someone would have used it had it never been open sourced in the first place. I think this is what people forget, they trick others into a low price of entry OSS, and then think, damn a lot of people use this I should make it paid. But had it been released closed source and paid from the start, you would have quickly learned the market for it isn't there in a closed paid model. And now the downside is you can kill both your open source project as well as your paid one in one go.


As for tap>, I think its worth mentioning that it is not a major feature, and its totally fine to never use it, think of it like data literals, its cool that it is there sometimes for some people, but its also a bit niche and not something that you'll always be using. So like, don't worry, there is no "HA AH!" eureka moment with it like say with transducers or specs. It sends data to an async buffer that things can subscribe to and do whatever. It does so in a way you have no control on the buffering, so you can't really use it for when you have that use case yourself, so what you would do with tapped things need to be stuff you don't care that much about that are not critical, which tends to be debug and dev type things.


thank you all for you input. Now I understand tap> 🙂


My biggest beef with tap> is that it returns a boolean, instead of what was tapped, though its super easy to wrap it and have a spy> fn instead


@U0K064KQV There's a tap-> coming "soon" that will let you thread through it.


And you can always use (doto tap>) in a thread pipeline or (doto expression tap>) to do it "in place" and get back the original value.

🆒 4

(a bit off-topic but I used doto in an interesting way yesterday):

(doto (fs/file (fs/temp-dir) "neil" "deps.edn")
  (-> fs/parent (fs/create-dirs))


Ya I forget that I can use doto with other things than Java interop


Speaking about tap> and add-tap (which I mostly use to print out things), does anyone know a simple way of including line of code in the output?


You can wrap it in a macro that uses the meta on &form to do so.

Daniel Miladinov23:09:41

So, in Clojure, the naming convention for predicates, or functions that return a boolean, is to end their names with `?` Is there a naming convention for functions that return predicates?


Functions that return pred... hum not that I know of


But I tend to call my constructor functions: make-x so you could have something like make-x-pred

Daniel Miladinov00:10:00

Thanks for replying!


yeah that seems reasonable, or pred-whatever-the-things


as a suffix, easier to scan like @U0K064KQV say


what is a predicate, anyway?


something-premise ?


Not a word with many synonyms, this predicate word. Verb-phrase sorta works but does not translate perfectly to code land... If you have a concrete example maybe we could come up with lots of alternatives.


I often suffix with -fn.

Daniel Miladinov00:10:05

Thanks for replying!