Fork me on GitHub
Jan K12:02:25

Is there a predicate to check for a multimethod? Something like fn? (which returns false for multimethods)


well, there’s methods, but I’m not sure what happens when you call it on a non-multimethod


There’s not a predicate in core afaik because Clojure chooses to treat them transparently the same as functions everywhere and discourages doing otherwise. However, you could always do something like (instance? MultiFn thing)

Jan K16:02:25

If they were treated the same, then I'd expect fn? to return true for them, that would work for me as well 🙂 I just want to distinguish non-function values (including collections) from functions. Thanks for the ideas, the instance check seems like a good way.


I would expect fn? to return true as well. Kinda surprised it doesn’t. It looks like MultiFn extends AFn implements IFn and the fn? implementation is

(instance? clojure.lang.Fn x)
…. so difference between IFn and Fn. I don’t know why


Clojure 1.9.0
(ins)user=> (defmulti foo identity)
(ins)user=> (ifn? foo)


Hi can you guys recommend a good open source application code to read? especially in the context of slightly more intermediate/advanced, clojure techniques i.e. transducers, use of spec, use of namespace-qualified keywords etc., cheers!


I need a dynamically sized collection of agents, but the size of that collection will be managed by another agent (changes to the size of the collection will be significantly less frequent than changes to the underlying agents). Is nesting agents in this case appropriate, or am I missing a better way to structure this? eg. (def things (agent {:thing1 (agent 1) :thing2 (agent 1)})) , then (send (:thing1 @things) inc), and (send things assoc :thing3 (agent 1))


hi, it seems to me it's not possible to specify a mandatory option for toosl.cli


the only thing i can do so far is to: :default-fn #(if (nil? (:id %)) (throw (IllegalArgumentException. "--id is mandatory")) %)


I think options are always optional unless you do something like that. Use arguments for mandatory arguments. Sorry that sounds a bit tautological.


Trying to spin up a old (eh, ~two months) project of mine, and when running lein ring server-headless, I get the following endlessly long stack trace: As far as I can tell, the error is not related to my code, as it's not part of the stack trace. But I'm unable to find any entrypoint or obvious place to start looking for issues. Could someone provide some pointers?


Looks like it’s probably related to an old version of clojure.core/unify that does something incompatible with clojure 1.10 / spec. It looks like Alex probably fixed that here: and that you could resolve it by explicitly declaring a version of [org.clojure/core.unify "0.5.7"]


Huh, that's super helpful! Thanks a lot for taking a look and even coming up with a solution :thumbsup:

🤞 5

Hm, doesn't seem to resolve the issue though. Specifiying it in my project.clj still has the same error. Also worth mentioning, I'm on clojure 1.10.0, and 0.5.7 of core.unify seems to have been released 2016.07.25 so I expected it to be used already


Are you using cider? If so, update to latest version.


nope, no cider. lein ancient also tells me all artifacts are up-to-date so everything is updated


How about updating lein itself?


do you have a ~/.lein/profiles.clj that might be interfering ?


or that ^ 😛


I remember bumping into that same stack trace but updating all deps resolved it.


already on latest lein. Thanks for the profiles.clj, will check that out


hm, no luck, commented out everything in profiles.clj, ran lein clean and still same error


gonna try downgrading lein instead, have solved issues in the past


i still think you have an old version of unify on the classpath. just a question of how it’s getting there


Mmm lein plugins in project.clj? Especially lein-ring


@U5RCSJ6BB seems so. lein deps :tree does not list unify anywhere, but guess it's possible it's embedded somewhere somehow


@U6N4HSMFW yeah, had three plugins there but commented them away


yeah! Thanks @U6N4HSMFW! Upgrading lein-ring solved the issue!

💪 10

My assumption that lein ancient upgrades everything was wrong, as it doesn't update plugins (by default at least)


the Clojure community continues to surprise me with it's helpfulness! You're all awesome folks! :beach_with_umbrella:


thanks a lot for helping me tracking it down


No problemo!


Is there a designated channel @alexmiller posts his weekly update blog post link on? I can never find it reliably.


Ps. Those posts are great.


i've seen them reliably show up on reddit


And in the reddit thread today it was mentioned he is posting about them on a zulip stream: I haven't quite wrapped my head around this zulip thing yet myself

Alex Miller (Clojure team)16:02:30

I have been posting on reddit and now on Zulip and erratically here :)

💯 10

I have started subscribing to RSS feeds again, mostly to keep up with interesting Clojure news. seems to be a good choice for me.

👍 10

Is there a format to give examples in docstrings/elsewhere for (pure) clojure functions that can then be exploited by other tools? (e.g. to check the examples, etc)


Also, another question: in my current project I find myself wanted to use maps with namespaced keywords over records because they have a lot of very nice properties (play well with specs, serialise well, are extendable, etc), but I really, really miss having something like protocols. Is there anyway to get the best of both worlds?

Alex Miller (Clojure team)19:02:46

have you experimented with multimethods?


@alexmiller it depends what you mean by experimented. I am aware of them and have used multimethods in a few places, but I wouldn’t say I have a good intuition on how they can be used to address a variety of problems


for example, I have a datastructure in my application that is essentially a tree. If I implemented it using a record I would make it extend a “ITree” protocol (or similar) and define some standard tree functions on it, but because I am using maps it seems like I am forced to define all those tree functions specifically for that datastructure


With clojure 1.10 you have :extend-via-metadata on protocols so plain maps can implement protocols using meta


holy moly really?

Alex Miller (Clojure team)19:02:32

^^ although there are some caveats


what are the caveats @alexmiller?

Alex Miller (Clojure team)19:02:16

satisfies? doesn't work with it (although generally you should steer away from that anyways)

Alex Miller (Clojure team)19:02:47

and they are slower than record protocol impls although how much that matters to you will depend


out of curiosity do you (@alexmiller and others) shy away from using records for application code? I know they’re used for clojure core / libairies (e.g. seq, etc), but their incompatibility with specs seem.. discouraged


slower doesn’t matter at all to me


and Clojure seems to be very much the spirit of using attribute granularity (as illustrated by spec using namespaced keywords, etc), which records are not


sorry not protocols; records*


and if you use protocols, do you use them with maps?

Alex Miller (Clojure team)19:02:51

I'd say records are good in their niche, but that niche is relatively small


In clojure applied, examples use records instead of maps 😜


but I'm still in the first chapter

Alex Miller (Clojure team)20:02:43

yeah, I wrote it :)

😄 5
Alex Miller (Clojure team)20:02:03

a second edition would probably be different

👍 10

yep, hence my curiousness, your comment here vs the book

Alex Miller (Clojure team)19:02:02

definitely use protocols, but don't extend to generic map type


to generic map type?

Alex Miller (Clojure team)19:02:27

I don't typically use protocols with maps


hmm, and so do you not define generic functions on map? e.g. using generic tree functions on a map that represents some kind of tree


(e.g. map, fold, etc)

Alex Miller (Clojure team)20:02:50

I don't typically have those kinds of data structures

Alex Miller (Clojure team)20:02:28

but usually stuff like tree-seq or clojure.walk/postwalk are useful with trees