vim

walterl 2022-11-05T00:25:26.067229Z

https://github.com/walterl/conjure-tapdance

👀 1
❤️ 1
🚀 3
2022-11-07T14:19:11.410599Z

We have used taps with integrant for local development fakes for methods that would call out to AWS Services in prod-like environments. e.g.

(defmethod ig/init-key :aws.sns/tap! [_ _]
  (fn [message] (tap> {:my-ns.tap/type :aws.sns/publish ::value message})))
by tapping a map with a namespaced type key and a namespaced value, it allows us to have taps to listen to the various types of events that we have.

2022-11-07T14:21:16.721719Z

so there are things like SNS, SQS, and some others, where we could add-tap a general pprint , or have other taps that pick things up and feed to channels that represent our SQS Queues or SNS Topics that invoke other local running lambdas in the same project.

2022-11-07T14:23:08.887029Z

e.g. if we want to do local dev testing of a HTTP request comes in, invokes a lambda that puts a message on a queue to work, and watch the other lambda do its thing

2022-11-07T14:26:00.403949Z

the tap by default is off so we don’t get that behavior, but by using the tap, we can do an add-tap that will look at data an do a dispatch to a channel that we started that acts like the AWS queue processor that feeds data from that channel to the lambda’s handler function

walterl 2022-11-07T14:35:28.124239Z

Another (less impressive) usage I just employed: Using a tap>-based log publisher with mulog, to get all my (structured) logs in Portal.

2022-11-07T14:38:24.295119Z

@clojurians-slack100 are you doing tap> calls directly, or do you structure the output of the tap so you can tell that it came from a call by your plugin vs something else?

walterl 2022-11-07T14:39:42.295989Z

Directly. Mulog already adds a few keys with the :mulog/ ns, so it's pretty clear.

2022-11-07T14:39:43.620109Z

was part of the reason we put the value in a map, so in our calls it gives us “metadata” around the source of the tap

walterl 2022-11-07T14:40:47.746809Z

Yeah, that makes a lot of sense for how you're using it 🙂

2022-11-07T14:44:46.844309Z

wasn’t sure if you distinguished between this is a tap> call in the code, vs this is a manual intervention of a tap> call

2022-11-07T14:46:09.247499Z

e.g. if you call it with this plugin, you might want to easily filter out, or know that it was a debug/interactive invocation vs ones that happened in the course of the system running “naturally”… for some definition of naturally 😉

walterl 2022-11-07T14:52:34.927269Z

The plugin doesn't wrap the data in anything other than a tap> call, no, but that's quite an interesting idea. Shouldn't be too hard to wrap it in a map with a user configured key too. So it becomes (tap> {:user.configured/key tapped-value})

Chase 2022-11-05T01:24:44.814129Z

This is timely, I've been wanting to explore taps. Do you happen to have a resource explaining them? It's a tool for data inspection right? And other tools like Portal and rebl provide a graphical interface for these taps or what? What is your workflow with this? Hope that's not too much questioning haha

martinklepsch 2022-11-16T13:54:30.522059Z

This is pretty cool. I’ve been using tap> mostly for promises in node REPLs because otherwise there’s not an easy way to view the results of a promise (async println is wonky). Would there be a way to do something like #(.then % tap>) but only if the value returned is a promise?

Abhinav 2022-11-17T05:20:47.782199Z

This is cool. I wrote something similar, it’s a macro that injects inline defs in functions. I’ve been using it as my sole debugger on neovim. https://github.com/AbhinavOmprakash/snitch

❤️ 1
walterl 2022-11-06T11:35:31.599869Z

Oh, and allow me to ruin my own newborn plugin with a Portal feature: https://github.com/djblue/portal/blob/master/doc/guides/nrepl.md. With that enabled every REPL eval's return value is automatically loaded into Portal. No tap required. 😅

🥲 1
Chase 2022-11-06T18:41:54.502689Z

lol, yep, that is quite convenient

walterl 2022-11-05T12:29:25.353509Z

That's a fair point. It took me a while to figure out what they are and how to use them too. Taps by themselves are really just junction points for data flowing through a program. By itself calling tap> does nothing. It's only when you hook something up to it, with add-tap, that that "something" (a function) gets called with the tap>ped data. What you connect to your taps are up to you. As https://clojuredocs.org/clojure.core/tap%3E#example-612f72eee4b0b1e3652d7538 shows, it could be as simple as clojure.pprint/pprint. In practice it will often be a data exploration tool like https://github.com/vlaaad/reveal, https://github.com/djblue/portal, or Cognitect's https://docs.datomic.com/cloud/other-tools/REBL.html. These tools make it a lot easier to navigate data, especially deeply nested data structures that we often find in the Clojureverse. I've only used Reveal and now giving Portal a shot. Both of them have, for example, table renderers for "sequence of maps" kinds of data, which is incredibly useful for inspecting data. Here's an exception's stack trace being rendered in a table, just as a (rather bad) example:

walterl 2022-11-05T12:34:07.137269Z

Re workflow: I tend to use taps only for debugging and data exploration, using Reveal or Portal, during development. It's a great companion to REPL driven dev, allowing you a more efficient view of the data you're working with. That's where this plugin comes in: if you quickly want to tap a var/form to inspect its value, it's just a little quicker to use a mapping, than to manually wrap the var/form in (tap> ,,,) and eval it.

walterl 2022-11-05T12:36:11.279129Z

I know some people like to leave tap>s in their code, but I tend to remove them before committing. It could be useful to have "standard" tap points, but one of the drawbacks of taps is that you get no information about where the tapped value comes from. Unless, that is, you add it to the tap: (tap> {::frobnicator thing}).

walterl 2022-11-05T14:08:31.266169Z

> "one of the drawbacks of taps is that you get no information about where the tapped value comes from" Looks like Portal has that covered 💪 https://github.com/djblue/portal/blob/master/doc/guides/portal-console.md

Chase 2022-11-05T17:03:37.938459Z

That was an awesome breakdown, thank you!

Chase 2022-11-05T17:28:23.286159Z

I installed the plugin but when I open up neovim now I get these errors:

Chase 2022-11-05T17:28:34.392709Z

Chase 2022-11-05T17:29:49.607819Z

I haven't made the switch to a lua (or fennel) config so not sure if that is affecting this

walterl 2022-11-05T19:53:36.214779Z

Do you have Conjure installed?

walterl 2022-11-05T19:53:58.226219Z

Still, I think I'm using aniseed from Conjure rather than directly. Lemme check...

walterl 2022-11-05T19:57:40.676989Z

OK, it's updated to use the local Aniseed. You'll still need Conjure installed, though.

walterl 2022-11-05T19:57:47.329499Z

It does all the heavy lifting.

walterl 2022-11-05T19:59:03.124489Z

> "I haven't made the switch to a lua (or fennel) config so not sure if that is affecting this" You don't need to.

Chase 2022-11-05T20:37:11.487239Z

Hmmm, I got a lot of errors when just installing the plugin now. So when you are saying it is changed to use the local aniseed, I assume that means I have to have aniseed installed? I definitely have Conjure installed in the sense that I use it daily. Not sure if I should have something else going on though.

Chase 2022-11-05T20:37:56.551129Z

It's probably user error on my side though, so please don't worry about it. Maybe we can see if any others have issues.

Chase 2022-11-05T20:47:18.725139Z

I think I solved it. I had { 'for': 'clojure'} in my Conjure plugin settings. Removing that (or adding the same for your plugin) seems to have fixed it.

Chase 2022-11-05T20:50:29.299099Z

The cool thing about that little adventure of mine is that I had installed Portal and was playing around with it too so now that I have your plugin working I got to see firsthand the convenience it provides! haha

🎉 1
walterl 2022-11-05T21:10:31.121689Z

Thanks for the report on the source of your errors. One could probably jump through an extra few hoops to check if Conjure libraries can be loaded, but that'll require quite a bit of shuffling. I'll do so if this comes up often. 🙂