Fork me on GitHub
Drew Verlee00:06:23

does anyone know if there is a resource with all the short hands the clojure docs use. coll, val, f, etc…


so I think I know what you mean, but am a little confused, if you can clarify


I see coll and f used throughout the docs to mean any “collection” and “function”, respectively


but I haven’t seen a listing in one place of what all terms used in those docs mean


since they are function docstrings, and thus written by the authors of each function, I would assume there isn’t any universal system for anything in them


Is there a specific one you’re looking to demystify?


What has helped me when I hit a term I don’t know in the docs is to search for that term in the docs themselves, to see how it is used elsewhere.


@drewverlee sorry shoulda tagged ya


@alexmiller thanks! that also helps with my earlier questions about best practices with libraries

Drew Verlee00:06:29

@riptidebeach nothing in particular, i just noticed a theme and wanted to follow it. I was trying to decided if maps was a good idea/bad idea. I decided on bad, and it called it coll. i’m wrapping up the 4clojure problems so the names are rather abstract. Actual, that’s a sigway into a topic i come back to a lot, which is naming things. I tend to think that coll would be a bad name in most apps where a more domain specific name could be used. Does the clojure community have a particular feeling one way or another on this?

Drew Verlee00:06:53

@alexmiller Thanks alex, ill have a look.

Alex Miller (Clojure team)00:06:05

coll is a great name in a generic higher order function

Alex Miller (Clojure team)00:06:25

in an app function I’d probably prefer something like customers


yeah I only see things like coll in higher order code like alex said

Alex Miller (Clojure team)00:06:33

maps seems ok if it’s a generic function that takes a collection of maps

Drew Verlee00:06:04

@alexmiller thanks for weighing in. I have been doing as much for years, but it never hurts to ask.


@drewverlee I’m curious about maps, even with ^what Alex said. Given that map is something you can do to a functor, and then maps will perform the same operation on 1 or more functors (I presume?), I’m curious what your use-case for maps is


seems kinda cool maybe?

Drew Verlee00:06:14

@riptidebeach drastically less cool then that :). It was a parmater name for a list of hash maps 😥


then that makes perfect sense as a name


In clj-time, to calculate the span interval of two date-times. Like:


In clj-time, to calculate the span interval of two date-times. Like:

(require '[clj-time.core :as t])
(require '[clj-time.format :as f])

(def video-clip-timestamp-begin
  (f/parse (f/formatters :hour-minute-second-ms) "00:03:00.012"))
(def video-clip-timestamp-end
  (f/parse (f/formatters :hour-minute-second-ms) "01:12:15.007"))

 ;; get the `Interval` representation of two timestamps
 (t/interval video-clip-timestamp-begin video-clip-timestamp-end))
get result 69. But I want to get the interval with format like 01:09:23. How to do this?


@stardiviner There might be a better way to do it, but this should work:

(->> (t/interval video-clip-timestamp-begin video-clip-timestamp-end)
     (f/unparse (f/formatters :hour-minute-second-ms)))
where c is clj-time.coerce

Drew Verlee16:06:28

I have a habit of revisting fundemental topics over and over…. when is it a good idea to use a protocol over just a map? I read and i’m afraid I still don’t’ have a good intuition.


@drewverlee protocols shine when you are implementing them across different types, and combined with records (vs. maps) have much better dispatch performance vs. multimethods


the drawback, of course, being that dispatch is strictly limited to the type of the first argument to the protocol function


@drewverlee i'll quibble with that blogpost. there are no "OO features" in Clojure.


@mobileink Clojure has a la carte polymorphism so I’ll quibble with your assertion there…


(the question is really whether polymorphism is considered OO or not…)


I’d say many of clojure’s best features are the good parts of OO

Drew Verlee19:06:18

time to reread clojure applied (which has a section on the topic of records and maps). 🐴 :cricket_bat_and_ball: 💀


in deference to yawners, #off-topic

Drew Verlee20:06:13

Answering my own question: So the question i thought i wanted to ask was about when to use maps vs records. Which upon reflection is straight forward after considering what the are. Records provide a set of boundaries to communicate the fields, performance and a factory function. So ignoring perf, you would use records when your looking to create more then 1one of something. You wouldn’t want to require another set of logic to use instances of your record though, in which case you should send them a map. ^ from clojure applied. The question, i wanted to ask however was from the article i linked. The author says.. > Now when I build applications in Clojure I tend not to use Clojure’s OO constructs, protocols and types, for the domain data passing through the system. I’ve followed Rich and Stu down the path of values and data structures. First i realized on re-read he didn’t say anything about records. He says, protocols and type. I think i understand the argument against creating a new type. Which I assume is about not creating something that already exists. However, i’m not sure how you can replace protocols with values and data structures. I see one as primarly a mechnism for polymorphism and the other two as about … structure.

Drew Verlee20:06:40

^ hopefully thats not off topic


My reading of that is that they don’t use protocols etc within the domain model of their system, only for defining boundaries of their systems. Relying on standard data structures means you use (only) the core abstractions in Clojure within your domain model: sequences, associative, indexed, countable etc — and the huge base of core functions that are defined on top of those abstractions.


You already have that level of polymorphism within the core — regardless what data you are modeling, sequence-based functions can deal with it (or associative for some subset of that data, etc).

Drew Verlee20:06:44

@seancorfield so re-use the existing functions, only create new interfaces to communicate something new (possible your domain). Good idea: a protocol to clean different tools differently. Bad idea: a protocol to merge together vectors vs lists.


I think I’m hazy on the distinction too, I usually see the possibility to do something in using protocols or data, but that might just be because I’m not understanding in practice how you get the same advantages out of the “data” version as the protocol version.


For example:


(defn grid [cols rows]
  {:grid/cols cols :grid/rows rows})

(defn cell-count [grid]
  (let [{:keys [grid/cols grid/rows]} grid]
    (* cols rows)))


(defprotocol IGrid
  (-cell-count [_] "return the cell count in a grid"))

(deftype Grid [cols rows]
  (-cell-count [_] (* cols rows)))

(defn grid [cols rows]
  (Grid. cols rows))

(defn cell-count [grid]
  (-cell-count grid))


To me the protocol version is more flexible, but I’m suspecting that the “data” version might be misinterpreting something


(def grid [5 2])


; grid with 5 columns and 2 rows


it’s just data. Good names and comments beat overenginering 🙂


In this example IMHO it depends on if the grid is a one time static thingy or do we need many dynamic grids.


@U068UBMJR I’m usually thinking about things from the perspective of creating an api for someone else. Like you said names are a big part of that, so maybe something like this:

(def grid "takes cols and rows" vector)
(def cols "gets the cols from a grid" first)
(def rows "gets the rows from a grid" second)
(def cell-count "the number of cells in a grid" (partial apply *))


Yeah, I think that’s what he’s getting at.


Sometimes it comes down to the granularity of your “systems”, e.g., when using Component, what do you “encapsulate” into a record + protocols?