Fork me on GitHub

@patrick.glind If you don't mind paying for some high quality video tutorials, I'd recommend Eric Normand's -- especially the REPL-Driven Development course.


I think Timothy Baldridge also has a good series of (paid) videos.

❤️ 4
👍 4

Which projects are good examples of idiomatic clojure code to look at?


What’s the series on YouTube that mike fikes and others do? I’m forgetting the name now but they do a repl based problem solving for the second half of their broadcasts. Not sure if still active though


Eric Norman was involved as well. (Since you bought one of his books)


Yes. Thanks @mfikes didn’t want to ping you during the holidays :)


No prob :)


Also not totally clear on the etiquette about when talking about someone but don’t need to ping/bother them


@ludvikgalois Not sure what I'd point you to as an answer to that very open-ended question... I'll be interested to see what folks actually suggest.


Right, I often avoid @ mentions for the same reason—evidently it can trigger on your last name. :thinking_face:


Every time I mention the Corfield comma, Sean gets pinged. 🥴


I’d suggest Tim’s Clojure Tutorials but their subject matter is pretty niche - like DIY JITs, interpreters, logic inference and query engines etc.


which is why I find them super interesting btw.


Heartily agree on that. Tim is super interesting and has a great patient voice as he explains


Ah, I've never watched Tim's videos so I didn't know what was in them. Good to know.


Hi! I'm writing a simple parser to read MP3 tags from input stream, using core.async.

(defn- read-frames
  [parse-map contents]
  (let [stream (:stream parse-map)
        fchan  (chan)
        result (go (loop [frames {}]              ;; conj frames to resulting map
                     (if-let [f (<! fchan)]
                       (recur (conj frames f))
    (loop [left (:remaining parse-map)
           id   (d/frame-id stream)]
      (if (and (> left 0) id)
        (let [n (d/uint stream)
              _ (d/skip stream 2)
              x (d/ubytes stream n)]              ;; read binary data
          (put! fchan (or (f/frame id x) {}))     ;; convert binary to frames
          (recur (- left (+ n 10))
                 (d/frame-id stream)))
        (close! fchan)))                          ;; close when no more data left
    (assoc-in parse-map [:tag :frames] (<!! result)))) ;; wait for result
Previously I tried using (go ... f/frame ...) instead of (put! ...), and it happened to work slower. I want all (f/frame ...) calls to work concurrently, and in the end they should all conj the result into a map, which will get returned at the end. Can you suggest any improvements to this?


Thank you everyone for your suggestions! I did find Eric's videos however are too much for my budget right now, I will check the others

Bobbi Towers10:12:15

Sounds to me like you might get a lot out of these

👍 4

hi everyone! , is there an open source project that heavily uses core.async? I would like to study how it is put in use.


question about clj-time and specifically timezone shifting: If I shift a date-time object using the offset functions like this: (time/to-time-zone (time/now) (time/time-zone-for-offset -6)) and then print the value using str, the value printed contains the correct date. That is, if the offset shift spanned midnight, the earlier date will print post-offset. This all seems correct. However, if I call clj-time.format/unparse on the date-time object using a format string which results in just a date, no time (for example yyyyMMdd) I only get the date post-midnight. I.e., it appears to be unshifted. I'm wondering if I'm doing something wrong or of this is just a misunderstanding on my part about how clj-time is supposed to work.


Related, I can not use the various local functions in this case as I'm working with multiple timezones and there really is not a notion of local in this context.


Okay, answered my own question. Didn't see this in the docs, but clearly shown in the code. Looks like there are functions to wrap formatters with timezone information, among other things.


hi, I'm having some trouble trying to use crux with lmdb. I tried to use rocksdb before, but for some reason that didn't work at all (no locks or something) and it blew up the data directory to 200 MB immediately. now with lmdb it seems to work, but it feels like the process is hanging(?). right now my code only submits a few docs and then outputs all of them, lein run works within 20 seconds or so, but then the process just idles. lein uberjar ran for 2 hours and produced no results

time lein uberjar
Compiling rocksdb.core
Dec 30, 2019 3:04:33 PM$eval361$fn__364 invoke
INFO: unknown
Dec 30, 2019 3:04:33 PM$eval361$fn__364 invoke
INFO: Using libgcrypt for ID hashing.
real    115m3.416s
user    2m54.682s
sys     0m18.303s


I'm looking at both the main-figwheel and shadow-cljs tutorials, both advocate using CLI tools instead of lein/boot. CLI tools doesn't seem to provide you with a project structure though. Not that it's a big issue, but being totally new to it - it feels like you are missing out on 'good' practices when it comes to the project layout etc. Is there a boiler-plate project structure for shadow-cljs or figwheel?


I also plan to use Reagent


So would I structure it somewhat like a react app?


@glfinn83 I still like using lein

👍 8

@glfinn83 for shadow-cljs there’s, inspired by create-react-app

👍 4

I'm definitely going to look into this. Have you been using this in your projects?


Haven’t used it, though bookmarked it when looking for it recently. Went with one of the example-projects instead:


What's the best way to convert a seq of vectors (like ([k1 v1] [k2 v2] [k3 v3] ...)) into a map?


(into {} coll-of-kv-pairs)

👍 4

Quick Q: Does anyone know the origin of the Hiccup DSL? I feel like it’s James Reeves, but I just want to be sure i’m not missing someone. Thanks!


I have a question about protocol and defmethods. I have a map that represents a type [for exemple, a payment type] which has some specifics keys in it. Cool. However, I want to create a protocol and extend it to work with this specific map. I thought about using a defprotocol at first, and I worked my way up to define the interface signatures, however when I started to implement the methods itself I tried to use a defrecord but for this situation I would have to wrap my entire map in this defrecord. It does not look right to me. I should use a multimethod and dispatch on some key of my original map or there are better alternatives other than wrapping the data?


if you don't want the specific features or speed of a defrecord, use a multimethod

Alex Miller (Clojure team)18:12:35

Probably a good candidate to extend via metadata (see

Alex Miller (Clojure team)18:12:12

Just add the metadata to the map that implements the protocol


I sorta get it. I am looking for other examples to become more clear.


(def john-doe (with-meta 
                {:name "John Doe"
                 :language "us"} 
                {`clojure.core.protocols/datafy (fn [x] (assoc x :type 'Person))}))

(datafy john-doe)
{:name "John Doe", :language "us", :type Person}


the idea here is to have the implementation somewhere else and attach it on the fly, right?

Alex Miller (Clojure team)19:12:23

Yeah, you attach the implementation to instances, not classes


The only caveat is that sequence functions don't preserve meta, so if you do any tranformation on the map and put it back in a map after, that new map won't have the meta anymore. So you need to manually preserve it in such case.


thanks, learned something new today. I think to my scenario the defmulti fits better


This caveat applies to records as well, in that any sequence function will turn it into a seq, losing the type. So you need to explicitly make it a record of that type again yourself. With record, ots even worse actually, because a dissoc will also lose the type. So got to be careful.


in the interface there is no way to enforce the return value of an implementation, right? idk if I'm overthinking but this should be desirable?


Multi-method that dispatches on a key/value of the map doesn't have these problems. Granted that you always put that k/v back on your resulting transformed maps


Correct, can't do that :p


Untyped language hehe


You can provide a Spec for it though, to document the intent


But its up to the implementer to make sure they respect it


hehe I suspected rsrs


how can I provide a spec?


one more edge that I don't know if I'm doing it right is about the client that will use my interfaces. I would like for the user to require only one namespace but it seems that when the implementation lies in another file, I have to require both the interface and the implementation. But how the client would know where the implementation lives?


You would s/def a multi-spec for your multi-method.


[sorry, bunch of question prior to holidays hehehe.. very intriguing subject.. I am trying to grok this style of programming for a while now ^^]


You would either put them both in the same namespace. Or have one namespace require the other. And then the client that requires that namespace will have the impls namespace brought in transitively


just to be clear. I have 1) namespace with the interface and 2) namespace with the implementation which already imports 1)


you propose to create a 3) to require both?


If you want the clients to only need to import one namespace


But it gets tricky


I think in your case you're better off just moving the defmethods inside the same namespace as the defmulti


sounds interesting, I've done that on Python a lot.. init files with bunch of imports lol


this option is not that good, right now I have three different types that are extending the interface


great, this looks like the perfect fit for the problem


I can't remember if it works with mutlimethods though. Should be easy to try though.


I'll try it later, thanks


do you have more material to recommend about oop in fn-style [idk if I can say this hahaha]?


Otherwise sometimes people just do it manually. So you have this single namespace with all functions and vars you want to expose. And you have them use your impl code under the hood.


I re-read a book I had about CLOS and was very interesting to see the amount of similarities with clojure system


That would include having a defn that calls your multi-method inside itself.


do you have any example of that?


Hum.. Can't think of any off the top of my head that's open source.


But I would not call it OOP


I think you should think of it as Polymorphism, and dynamic dispatch


What this does is, use the same function name for more than one behavior


But now that you're using the same name, how do you decide what behavior to choose? Where there are more than one? You do so by inspecting the runtime values


In other words. You could have a talk-dog and talk-cat function. One takes a dog map and another a cat map. No need for polymorphism at all. But if you want to abstract talk from cat/dog. Say because you have another function and it could take a dog or a cat as input, and it wants to make it talk no matter what the animal is


With talk-dog and talk-cat. That function needs to have a cond or case expression.


`(case (:type animal) :dog (talk-dog animal) :cat (talk-cat animal))`


But now if you have many functions who operate on animals. And all your type of animals share a lot of functions, talk, walk, sit, etc.


You'll have a lot of redundancy, where you're going to have case expressions everywhere


What you want is to delegate to the functions themselves, talk, walk, sit, etc. The responsibility of having the case expression and figuring out what to do based on the type of animal


And that's what multi method does 😛


Yeah, got it!!


But you could also just move that case inside each of them, though if you do that, they are closed for extension. Adding another animal can only be done if you have access to the source code, since you need to add one more case to case. Multimethod allows open extension, clients can add new cases to it even without access to the source code.


Anyways, my point being, there's nothing here that's OOP. There's no objects, no classes, no inheritance, no grouping of data and operations together


You can have a non polymorphic OOP language


It just so happens that popular OOP languages also support some forms of polymorphism in addition to their OOP support


if you compare to smalltalk (the paradiigmatic OOP language), and the designer's definition of OO, what multimethod does is closer to being OOP than what Java does


I never used smalltalk, but from my understanding its not so much polymorphism, its more about Actors


in smalltalk a method is a message (implemented as a string iirc), which an object dispatches on


conceptually described as an actor, but it's a polymorphic dispatch, just like multemethods


but it is true, in smalltalk the method impl is stored on the object keyed on the method name and in clojure it's stored on the multimethod and keyed on the class of the object (dispatch checks class then superclasses until it finds a match)


Hum... I guess you could see it that way. The object dispatches based on the message. Just like on Java an object dispatches based on the type.


I still don't think that was the point of smalltalk. At least from all the articles about what the real point of smalltalk OOP was. It seems it was more about the message being a string


java objects don't dispatch on type, methods are stored on the object


the connection I'm trying to draw is that regardless of the location of storage, a link is stored between a piece of data and an operation, such that code that is written in terms of the operation can figure out at runtime what to do with that data


and to me that's the interesting part of OO. I'm getting off topic here but I really think C++, Java, and all their descendants severely missed the point


Hum. I'm not actually super familiar with the underlying dispatch mechanism. Doesn't Java walk up the class hierarchy to find a method that matches?


I think I don't totally follow. To me, polymorphism is orthogonal to OOP, even though you can intertwine them. Such as choosing to use the class hierarchy as the driver for the polymorphic dispatch


But you don't need classes. You can decide to dispatch based on value, arity, some configuration, etc.


Even when I said dispatch on type, in Java types and Classes are also intertwined. But types also have nothing to do with OOP. Haskell hapilly has types and dispatches on them without having any classes for example


I don't know enough about smalltalk. And the smalltalk OOP might be a whole different beast and maybe that one is much more related to polymorphism. But that's just semantics. I'm talking about class based OOP, your classic C++/Java/C#/Python OOP


Where I might agree with you, I guess is that if I ask myself what an object is, its really just a set of fields and methods. And so you can think of it as the method to execute is based on the object you are calling the method with


And ignoring the class hierarchy and interfaces, you can think of it as object based polymorphism. But that is only true if by convention you have two objects where you choose to put a function of the same interface and name


I guess I see an object as a self referential collection of mutable fields and methods. Which I'm not sure how to implement in Clojure. But it be something like: `{:name "Shadow" :talk (fn [] (print "Woof, I am " (:name this)))}`


Assuming this map to be mutable


And a language designed around this particular structure as its foundational building block where all data and operations are organized using these objects to be an OOP language


So at this point, there's not polymorphism involved really


Now you could say if I also created: `{:name "Marble" :talk (fn [] (print "Meow, I am " (:name this)))}`


Well I just added polymorphism


Now if I do: ((:talk dog)) this will be a polymorphic dispatch based on the kind of object I have and the specific talk fn it contains


So I guess I see them as orthogonal, even though you can leverage objects for polymorphism, it doesn't seem you have too


But from what you said I gather small talk objects are different to this


Also, sorry, definitely doing some thinking allowed here


but the concepts terms have been likely been abused far past the point of being useful at this point


and to go back to @iagwanderson’s point above, it's not accidental that clojure has features that resemble CLOS


I have to reread the multimethod in clojure, but we also have the concepts of before-method, primary method, and after-methods?


no, we don't


hi everyone, did we ever come to consensus on what's the best data structure for something that resembles a ranked list or ranked map?


Not sure if I missed some previous discussion, but I'd think if you care about order you'd want either a list or vector over a map. Use a list of you are going to be re-ordering elements frequently, and don't care about random access. I'm under the impression vectors give you O(1) look ups of elements by index, but need to be pre-allocated so are not ideal if you will frequently be adding/removing/shifting elements around. Lists give you O(n) access, but can more easily modify elements they contain.


CLOS is in fact how polymorphism was introduced to lisp


(where entries move up and or down)


I've been using this dispatch on a project very timidly, but I already got the benefit of changing a implementation more than two times and not changing the interface. I very recently started at clojure and I didn't find many people advocating and showing examples of more intense usage of interfaces. Idk maybe I have missed something along the way. Do you guys think this subject is stressed enough in the community?


Changing an implementation without changing the interface does not necessarily require this kind of dispatch or polymorphism. A simple function will do


There a times where multi-methods are great, I'd say those are when you want users to be able to extend the behavior on their own. Or when you want more than one active implementation of the same interface


And protocols can make sense when you need the same, but over a coherent set of functions.


Its normally most useful for creating pretty generic abstractions. Like fundamental language constructs


Such as the collection interfaces, or the print multi method, etc.


I've rarely used them for application code though


For example Manifold is a good example use of protocols to create a very generic abstraction


we usually get the benefits implicitly by using clojure's built-in datatypes and using functions that dispatch based on interfaces

👍 4

most of the time that's enough, and it leads to simple flexible code


90% of my use of polymorphism in java is to stub/mock things out for tests. clojure has with-redefs so I don't need it for that


that said, component definitely puts some focus on interfaces, at least for services


anybody got an idea why crux + lmdb runs fine in my repl, but takes forever to finish the process when it's run using lein run (or has never finishes when doing lein uberjar)? I'm just outputting all 4 values and then close the node, is there something I'm missing?


you're starting a node at compilation time


well, file read time I guess. "compilation" is probably the wrong thing to say


compilation makes sense to me: clojure compiles every form before running it, and runs every form when loading a file


it's possiible to read a file without compiling / running, but uberjar doesn't do that


(and it's only useful fo preprocessing / analysis - you just get lists of symbols and such)


I'm just planning to use it as a db to store some data for a small project, ideally I can just give somebody the .jar, they run it and it starts the node and closes it after it wrote the necessary things to it, should take like 10 seconds max. but I'm guessing this is not the right approach then, other recommendations for what I should be using for this case?


you shouldn't define the db at the top level of the file - you can have a function that makes the db, and run it inside your main method


I see, I thought I'm just defining the db at that point and it's not run yet


or evaluated rather


right, that's a common misconception - side effects inside def run when the file is evaluated, and with standard uberjar with aot, that includes jar packaging time


the reason that lein run takes so long is another question - one thing to try is adding a call to (shutdown-agents) at the end of your main right before exit (it closes down clojure's auto-scaling thread pools so the vm can exit, but should only be done at exit, it's a one way switch)


will try that, thanks


could you also help me to define a function that makes the db, as you mentioned before?


my recommendation:

(defn start-db []
  (crux/start-node ...))

(defn -main [& args]
  (let [db (start-db)]
    (function-that-uses-db db)))

🙂 4

there are libraries like stuartsierra/component and integrant that simplify the above pattern but in early stages that's exactly what you want


thanks! I think I'm confused about the "def ^crux.api.ICruxAPI" part, just copied that from the getting started guide


that is attaching metadata to the var that is storing the started db


that's something that works in a simple example - it defines the db as a global, and the ^type notation tells the compiler what the type contained in the var will be (not really needed here at all)


oh it's a typehint. noisesmith is right. not sure how I forgot that. so metadata on the var that describes the type of the object. and yeah shouldn't be needed while sticking to the clojure api for crux


both descriptions are correct - the compiler uses the metadata


in this case I suspect the type hint is actually there for the human reader who understands how typehints are used (it's telling you the class of the object returned in that call)


after wrapping start-db in another function and adding (shutdown-agents) to the end of -main I still get the same behaviour when trying lein run


maybe add (.close db) as well. crux may have its own thread pool


you can use Control-\ when running in a terminal to see the stack traces of all running threads - one of them likely exposes what's blocked

🆒 8

the jstack command does the same, but takes a PID and runs in a different window


I already had (.close db) in my main, that's the weird thing


for the uberjar question: this is a common pitfall for newcomers, clojure doesn't have a "compile" mode, any code inside def is run when compiling


how can we define union types with spec ?


There’s actually a good example on

(s/def ::query string?)
(s/def ::request (s/keys :req [::query]))
(s/def ::result (s/coll-of string? :gen-max 3))
(s/def ::error int?)
(s/def ::response (s/or :ok (s/keys :req [::result])
                    :err (s/keys :req [::error])))


(s/def ::response (s/or :ok (s/keys :req [int?])
                        :err (s/keys :req [string?])))

(s/conform ::response {:err "toto"})
;; => [:ok {:err "toto"}]
Am I missing something ? because the answer seems wrong from the repl


req takes the key names as fully qualified keys which will use the spec of the same key to validate the value of the map for that key


Since your map is using an unqualified key :err you need to use :req-un


`(s/def ::ok int?) (s/def ::err string?) (s/def ::response (s/or` `:ok (s/keys :req-un [::ok]) :err (s/keys :req-un [::err])) (s/conform ::response {:err "toto"}) [:err {:err "toto"}]`


> Creates and returns a map validating spec. :req and :opt are both > vectors of namespaced-qualified keywords.


So you can’t check against directly against a predicate with s/keys


You must define a separate spec for the keys you’re checking and validate/conform/explain from there


@dimitri.tavan If you use the specs from the docs, and call this. It will be correct

user=> (s/conform ::response {::error 404})
[:err #:user{:error 404}]