Fork me on GitHub

What's the idiomatic or preferred way of writing a defxxx macro without turning it into a global`def`? I'm considering either using swap! on a global registry atom, or rewriting into a multimethod dispatch


Defining a def* macro is a super-common anti-pattern in the clojure community. I’ve seen it done 100 times poorly and not once well.


I’ve written and used def* macros many times happily and wouldn’t consider it an anti-pattern on its own, although any technique can be used poorly.


I mean, you can be wrong 😄


Your god-given right, bae


Happiness isn’t the factor I’m talking about. Many devs who wrote the ones I’m talking about are probably happy.


My point is: it’s basically never more effective/precise/flexible than an alternative.


(an example alternative being e.g. (def mything (mything foo bar)))


> anti-pattern in the clojure community my purpose is merely to interject that this is not a consensus opinion, and each case may be judged on its merits. many successful Clojure developers write and use def* macros. it’s fine to prefer lower-level primitives, also fine to reach for higher-level tools and learn how & when (/not) to use them. 🛠️


i'd just expand into a defn


doing that stuff manually sounds very dangerous


I want to have multiple 'types' of things that share the same name without colliding, eg.

(def-action foo 
(def-transformation foo 


I could of course intern a (symbol (str % "-action")) but that seems like an uglier hack


in that case i'd namespace them


actions/foo transform/foo


oh, even if there isn't an actual corresponding namespace?


just make a corresponding namespace


grouping functions like that is the purpose of namespaces

✔️ 4

that makes sense, thanks!

👍 4

I saw that Meander uses a system of global "registry" atoms for its macros, and was wondering if that was a normal thing to do


is there a way to improve REPL I get with lein repl because that one doesn't work with directional arrow keys


@roklenarcic have a look at rebel-readline


Why does cljs require a different library? I though cljs repl was just a command in the standard repl, i.e. I run the REPL and then run (cljs-repl)


Either because of completion or repl envs, but there's a lot happening to make it work in that repl, which isn't standard by some measures

Eduardo Mata14:10:25

What library would y'all recommend to parse a sequence of same attributes maps in to csv

Alex Miller (Clojure team)15:10:53

usually, "parse" means read but the rest of your sentence sounds like "write"

Alex Miller (Clojure team)15:10:02

org.clojure/data.csv can do both


Defining a def* macro is a super-common anti-pattern in the clojure community. I’ve seen it done 100 times poorly and not once well.


In general, most would be better off using def or defn.


Even really common ones like defroute from compojure are less than ideal. You often want to close over state (e.g. a db connection) before your final definition. So make a fn that accepts any variables and returns the final state.

Eduardo Mata16:10:00

I have Record name Event with several keys. How can I cast the Event record in to another Record with similar keys?


haven't checked, but maybe map->OtherRecord?

Eduardo Mata16:10:10

@vlaaad @lukaszkorecki yes! that is what I needed thank you


I've updated the gist - select-keys is not necessary actually


you can just pass the record to map->OtherRecord

Eduardo Mata16:10:52

yup! I did not used select keys as the keys are similar.


I have an api library that allows a single stream of messages to be received and allows handlers to be attached to handle messages. I just realized that instead of managing my own handlers I could just have an atom which is always reset! to the newest message, and have users use add-watch to manage handlers. Is there a reason not to do that? Are there any examples of other libraries which use atoms in this way?


you could do that, but it appears to be shuffling stuff around, moving the handler business from the message connection to the atom, and it is not clear to me what the advantage would be

👍 4

@jjttjj for serialized strictly ordered things that only take one action at a time, sometimes an agent is a better abstraction than an atom (with a wrapping function that knows what action to pass to the agent)


since an agent implicitly queues the functions sent to it, and only runs one at a time without retries


Just curious, which is better for a cloud-native clojure backend? AWS or Google?


If you can run JDKs of pretty much any version on both, then it seems that the Clojure part of that question isn't terribly relevant? It becomes "which cloud has better APIs / infrastructures for back end development"?


Sure, good point


last time i took a look around the integration between aws components was better. and i haven't looked around in the last 2 years anymore (since our company will probably never leave aws, it just wouldnt be economical)


@U6MHHF36J For what you’re using, is AWS cheaper than alternatives then?


no i mean converting stuff to a different platform would just take enormous amounts of effort

👍 4

talking about man years in effort. just not worth it, even if someone else is 25% cheaper in hosting costs.

👍 4

Big question, I know, just wondered if anyone had any strong opinions. Or if one was better tool-supported than the other


Don't think either is better for clojure in particular


Aws generally has higher adoption, so support is generally higher. But not clojure specific.


Sure, I noticed Cognitect had AWS-native consulting. Wondered if that was for any particular reason other than general AWS adoption


Market share - Amazon was first so it capture the majority of the market. Both Microsoft and Google are catching up and do not have as many offerings in their cloud catalogue as Amazon does, though Microsoft is certainly catching up.

👍 4
Kazuki Yokoyama20:10:14

Hi, everyone. Which channel is recommended for technical questions (StackOverflow like)?

Kazuki Yokoyama20:10:28

Cool! But is there any channel for this same purpose here in Slack?


Most channels here are for technical questions. But your original question asked for something "StackOverflow like"; is more like SO than Slack.


@UNZQ84WJV Specifically, Slack is temporary -- the free plan only let's us see the last 10,000 messages across the whole set of (hundreds of) channels so after a few days your questions (and answers) will no longer be visible.


Many channels are mirrored to Clojurians on Zulip which is searchable (and has a full archive of those channels from early 2019 on). But it's a one-way mirror -- messages typed into Zulip don't appear here.


So is the StackOverflow for Clojure in terms of questions & answers staying around "forever".


If you want real time help, Slack can be great. Novice questions can be asked in #beginners (where folks have opted in to help). More advanced questions can be asked here #clojure and if you have questions about specific topics or libraries, there is likely to be an appropriate channel for that too.

Kazuki Yokoyama20:10:44

Alright, thank you all. It makes a lot of sense for me.

Alex Miller (Clojure team)20:10:27

ask.clojure has the benefit that it will suggest similar questions to yours when you start adding it (and maybe you'll find the answer already exists). If it doesn't, then someone will answer it and the next person will find it. Whereas slack questions (while archived various places), are nearly impossible for someone to find later.

Kazuki Yokoyama20:10:40

And is ask.clojure preferred over SO by the Clojure community?


Hard to say. ask is fairly new but it is dedicated to Clojure and it also includes all of the JIRA issues that were active at the time ask was set up, so it has a lot of history around issues. I hope it will become preferred (although I still monitor questions on SO about Clojure).

Alex Miller (Clojure team)21:10:41

I'd say SO is under-used in Clojure vs other language communities


anyone know offhand how to spec a s/coll-of of alternating integers and uuids?

Alex Miller (Clojure team)21:10:27

(s/* (s/alt :i int? :u uuid?))


I am not sure of the meaning of your English description, but perhaps you wanted this instead? (s/* (s/cat :i int? :u uuid?)) . Alex's version allows all integers, or all uuids, or arbitrary mixes of both in any order. The latter one only allows int1, uuid1, int2, uuid2, ...

Alex Miller (Clojure team)00:10:07

oops, sorry, that's what I meant :)


I'm trying to figure out what the error here is

{:type clojure.lang.ExceptionInfo
   :message "error parsing spec form"
   :data {:k :marketplace.accounting.keys/funding-channel-id, :m (nilable (or :uuid uuid? :string string?))}
   :at [clojure.core$ex_info invokeStatic "core.clj" 4739]}
  {:type java.lang.Exception
   :message "Unable to resolve spec: :uuid"
   :at [clojure.spec.alpha$reg_resolve_BANG_ invokeStatic "alpha.clj" 69]}]


is that the wrong way to use s/or? I haven't touched spec stuff in a while, I'm trying to describe a field that can be nil, uuid, or string (for historical reasons all of these must be accepted)


are you sure you are using s/or?


here's the diff

+(s/def ::funding-channel-id
+  "The identifier for the funding / repayments channel for the loan this trade is for."
+  (s/nilable (s/or :uuid uuid?
+                   :string string?)))


user=> (s/valid? (s/nilable (or :uuid)) "foo")
Execution error at user/eval142 (REPL:1).
Unable to resolve spec: :uuid


I thought the args to s/or were keys alternated with specs


they are, I am using clojure.core/or there and getting a similar error message to what you are getting


OK - nothing in my diff from master has or, only s/or, and only in the spec where I see that error


but this could be a misleading error because our lib does some funky things with spec merging


the string "error parsing spec form" doesn't seem to exist in the spec repo


(spec 1 I guess, haven't checked spec 2)


yeah, then this is internal to our lib, and I need to resolve this with internal resources, thanks