Fork me on GitHub
#clojure
<
2019-02-23
>
Jan K12:02:25

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

eraserhd14:02:43

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

rutledgepaulv15:02:10

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.

rutledgepaulv16:02:56

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

noisesmith18:02:12

Clojure 1.9.0
(ins)user=> (defmulti foo identity)
#'user/foo
(ins)user=> (ifn? foo)
true

prnc13:02:53

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!

pachydermballet14:02:13

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))

pinkfrog14:02:35

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

pinkfrog14:02:33

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

Chris15:02:29

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

victorb15:02:28

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: https://gist.github.com/victorb/81eb2afacce8ca8d1731f399bbeb34d0 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?

rutledgepaulv15:02:40

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: https://github.com/clojure/core.unify/commit/a5f60d74e1df61291535be43dab7bd2f2eaceb32 and that you could resolve it by explicitly declaring a version of [org.clojure/core.unify "0.5.7"]

victorb15:02:16

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

🤞 5
victorb15:02:46

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

valtteri15:02:13

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

victorb15:02:51

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

valtteri15:02:13

How about updating lein itself?

rutledgepaulv15:02:15

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

rutledgepaulv15:02:22

or that ^ 😛

valtteri15:02:29

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

victorb15:02:34

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

victorb15:02:22

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

victorb15:02:46

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

rutledgepaulv15:02:45

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

valtteri15:02:45

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

victorb15:02:30

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

victorb15:02:44

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

victorb15:02:43

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

💪 10
victorb15:02:13

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

victorb15:02:41

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

victorb15:02:00

thanks a lot for helping me tracking it down

valtteri15:02:32

No problemo!

mikerod16:02:17

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

mikerod16:02:20

Ps. Those posts are great.

dpsutton16:02:04

i've seen them reliably show up on reddit

Chase16:02:42

And in the reddit thread today it was mentioned he is posting about them on a zulip stream: https://clojurians.zulipchat.com/#narrow/stream/187050-inside-clojure-journals 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
danieroux18:02:59

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

👍 10
hmaurer19:02:17

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)

hmaurer19:02:41

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?

hmaurer19:02:35

@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

hmaurer19:02:46

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

vlaaad19:02:17

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

hmaurer19:02:30

holy moly really?

Alex Miller (Clojure team)19:02:32

^^ although there are some caveats

hmaurer19:02:59

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

hmaurer19:02:39

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

hmaurer19:02:48

slower doesn’t matter at all to me

hmaurer19:02:25

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

hmaurer19:02:27

sorry not protocols; records*

hmaurer19:02:35

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

johnj20:02:20

In clojure applied, examples use records instead of maps 😜

johnj20:02:41

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
johnj20:02:17

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

hmaurer19:02:12

to generic map type?

Alex Miller (Clojure team)19:02:27

I don't typically use protocols with maps

hmaurer19:02:14

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

hmaurer19:02:18

(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