Fork me on GitHub
#clojure
<
2023-11-10
>
Ngoc Khuat02:11:03

Hi all, anyone knows a good way to debug defmulti? I’m trying to simulate the visitor pattern using defmulti , and I’m trying to find a way to debug what’s going on after each dispatch. What I want is similar to the trace tool in https://github.com/camsaul/methodical, you can trace a method call and it’ll print out a nested call stack like this

respatialized02:11:28

Make sure your dispatch points to a function bound to a var, then you can use with-redefs to rebind your function to a version with tracing in the context of the test/debugging

Ngoc Khuat02:11:02

hmm, does that mean I’ll need to use that var on all defmethods?

p-himik08:11:03

Another option would be to get the multimethods that you're interested in, iterate over their methods, and wrap each in another function that just reports what's going on.

p-himik08:11:57

And map-dispatch is a suitable replacement only in some scenarios, not all of them.

👍 1
Ian Fernandez08:11:38

Why is it suitable only in some scenarios?

p-himik09:11:49

Some existing libraries rely on multimethods - you can't get around those. They have a global state - sometimes it's desirable. They're extendable from anywhere, not just the initialization site. Multimethods support dispatch value derivation. Multimethods dispatch on a result of a function, not on a predefined field. Of course, the linked implementation can be adjusted for that, but there is still something that needs to be done there. Same for a potential default value.

☝️ 2
Ian Fernandez09:11:10

I don’t see how a global state is desirable + a very bad one to inspect is desirable. I tend to almost not use multimethods library You can always extend map-dispatch associng / dissocing keys from it’s registry importing default registries or making new ones Value derivation is a bad practice and sounds like inheritance

Ian Fernandez09:11:21

If something is so bad to debug and does not provide you a very amazing performance, it should not be used

Ngoc Khuat09:11:57

If the problem is debugging then I’d encourage you to try methodical, I think its performance is ~ with multimethod, and it has a great debugging tool. you can even define triggers for before/after a method execution.

p-himik09:11:51

I almost never have to debug something, but when I do, multimethods aren't a problem at all. Regardless if they use a custom hierarchy or derivation (which isn't related to inheritance all that much).

1
Ngoc Khuat09:11:51

same here, but since I’m trying to replicate the visitor pattern, the call build up data as it recursively calls the defmulti multiple times. so I want to see what’s in and out through each call

p-himik09:11:30

Oh, so it's calling (defmulti ...) multiple times and not (multimethod ...)?

Ngoc Khuat09:11:06

ah no, it’s call the-multimethod multiple times

p-himik09:11:19

As long as there are no new methods defined while you're debugging your code, iterating over the result of (methods ...) and re-defining all the methods with a wrapper should work just fine. If you need a more advanced approach, you should in theory be able to wrap defmulti and defmethod macros themselves. Finally, IntelliJ IDEA with Cursive has first-class debugging support. You can just step over the code as you'd do in e.g. Java.

👀 2
jpmonettas10:11:48

@U023C0QKU4W have you tried http://www.flow-storm.org/ ? It can provide you that same hierarchy of nested calls and other ways to look at the executed multimethods also