Fork me on GitHub
Michael Stokley00:01:55

i'm trying to model a singly linked list. I don't think hash maps will work because i want to allow same-valued nodes. what about a record?

Michael Stokley00:01:31

in python i'd use a class, and as far as i can tell the simplest "class"-like thing in clojure is a record


list and lazy-seq are already singly linked lists, I don't know why you would use a hash-map, how is that useful when each node has exactly one successor?


if you want to make a singly linked list in clojure and not use a list or lazy-seq (or something from java.util.Collection), the easiest thing is {:value foo :next bar} where bar is another hash with the same keys, or nil

Michael Stokley01:01:26

what would look like if i used a list?


in fact, there's a next method too


user=> (.next (list 1 2 3))
(2 3)


but it's better to use the next function, as it knows how to handle other types, and it's a first class value

Michael Stokley01:01:06

looks like that would work great

Michael Stokley01:01:31

but part of the exercise is deliberately using a more primitive data type, perhaps


function instead of method

user=> (next (list 1 2 3))
(2 3)

Michael Stokley01:01:44

where you're handling the nodes and nothing else, if that makes sense


sure - then you can use (:next l) if l is the hash map I initially proposed

Michael Stokley01:01:20

when would you use a record over a hash map?


+user=> (defn construct [x y] {:val x :next y})
+user=> (construct 1 (construct 2 (construct 3 nil)))
{:val 1, :next {:val 2, :next {:val 3, :next nil}}}
+user=> (def ls *1)
+user=> (:next ls)
{:val 2, :next {:val 3, :next nil}}
+user=> (:next (:next ls))
{:val 3, :next nil}


generally you would use a record if you need to implement a protocol or interface - if you have methods you need to overload

Michael Stokley01:01:25

ok, that makes sense.

Michael Stokley01:01:53

am i right in thinking the above example doesn't implement a protocol/interface that hash-map doesn't already have?


right - it literally is a hash-map


if you wanted it to print like a list, or be accepted by all the standard list functions, then you'd want to implement the Interfaces that define a clojure list


Im trying to build a simple rest-api with Luminus. just playing. would like to expose the guestbook as a json api. been googling for a while now and i still cant find a simple example for returning basic json data like array or simple objects from a given db query


@michael740 if you wanted to also make sure it wasn't a hash-map and couldn't be used that way, there's also deftype


@jstuartmilne there's a wrap-json middleware that can take a request handler function and return a new one that makes json - then you just return your data structure


@jstuartmilne any standard clojure binding for a database should hand you plain data structures as a result, then it's just a question of making the transforamtions (if any) needed to construct the data your client should expect


thank u @noisesmith I kind of got the theory behind it, just couldnt mange to find an example.


do you know of a working example to check it out.


where f is a function that takes a request and returns some data


interesting ill give that a shot


thanks again


np - I think the example in those docs should be enough to start with - though I understand if you haven't used ring much yet you'll want to play with the request and see what's in it


the good news is it's a hash-map, you can print it, look at the keys, use standard clojure data functions on it


ring is an exemplary clojure library in that it eliminates a lot of unneeded complexity to just let you use data


yeah i was going through the Luminus docks. and the documentation specifies By default, muuntaja middleware library is used to infer the response type when a route returns a map containing the:body key:


meaning it should infer


interesting - what did you try putting under that key? and what would it use to infer by?


or at least thats my understanding. Im surprised i could not find an example for a simple CRUD


(GET "/message" []
     :return      []
     :summary     "x^y with header-parameters"
     (ok (db/get-messages)))


OK - looking at the muuntaja repo, it looks like it adds the right headers if your :body contains a string that looks like json?


so been trying different things


oh, you have to explicitly call muuntaja's encode function if it is using that


i think the middleware does that


but what I don't understand is what tells it "make this json"


yeah you are right


im clearly missing soemthing hang on


anyway, looks like there's docs at the muuntaja repo (edited for better example)


thank u. i still havent figured it out but im not completly lost now


was the simplest thing


(GET "/message" []
         {:body {:data (db/get-messages)}})

Michael Stokley01:01:45

i'm trying to translate a simple tail call recursion into loop...recur

Michael Stokley01:01:48

(defn reverse_l
  (if-not (seq list_)
    (concat (reverse_l (rest list_))
            (list (first list_)))))

Michael Stokley01:01:05

am i correct in thinking my call to reverse_l is not in the tail position?

Michael Stokley01:01:09

and therefore i'd need to rework it into something fundamentally not recursive


yes, is not in tail position

Michael Stokley01:01:13

yeah, it throws a compiler exception right away.

Michael Stokley01:01:29

or rather, this does:

(defn reverse-l
  (loop [l l]
    (if-not (seq l) l
            (concat (recur (rest l))
                    (list (first l))))))


it can be recursive, but there are many options for recursion because of the limits of the JVM


in order to make reverse tail recursive, you need an extra argument representing the already-reversed


and then you are putting data into that, instead of the stack

Michael Stokley01:01:21

(reverse-l (rest l))?


the way you should reach first is to use the sequence abstraction


@michael740 to make it tail recursive it needs at least two args


so you end up with more convoluted code, and a helper function

Michael Stokley01:01:11

hmm. i thought loop was sort of the iterator?


if you work out on paper what the function is doing, you'll find that you need two accumulators as it recurs - you can't represent everything in one argument


loop is a target for recur - it's basically a goto label plus argument bindings


you need two bindings in the loop


if you want to tail call with recur, you can define a local fn that takes the extra arguments


@lockdown- loop takes as many args as you like, there's no need for a local function

Michael Stokley01:01:29

oh. the extra arg you're talking about is the accumulation?


the essential thing here is to recursively reverse an argument and not consume stack, you need to track two things - unprocessed items, and processed items


@noisesmith yeah, I said that because he can still make his main function take just argument (more elegant I think in this case) and inner function that recurs use the other args

Michael Stokley01:01:21

ok, this gets me on the right track... i'll work it out 🙂


@lockdown- right and what I'm saying is that loop takes as many args as you need, and that's the reason you use it instead of recur to the function itself (also a valid target for recur)


oh yeah, it can be loop or a local function


I would think the clojure way here would just be to use the sequence api abstraction


unless its for learning purposes


yes, we have to assume that what @michael740 is doing here is an exercise, the existing clojure.core/reverse does use the sequence abstraction (implicitly via reduce1)


the code is quite elegant for those who aren't doing this exercise by the way, figuring out why it works can be enlightening (and I'll spoil it a bit by saying it does use a two argument function but ... not exactly the way I am suggesting at first glance)

Michael Stokley02:01:58

(defn reverse-l
  (loop [to-reverse l
         reversed (list)]
        (seq to-reverse)
      (recur (rest to-reverse)
              (list (first to-reverse))


@michael740 check this out

user=> (source reverse)
(defn reverse
  "Returns a seq of the items in coll in reverse order. Not lazy."
  {:added "1.0"
   :static true}
    (reduce1 conj () coll))

Michael Stokley02:01:04

how do i see the source code for reduce1?


for now you can mostly ignore reduce1 and just look at reduce - it's defined in clojure's java code iirc


oh - reduce isn't much helpful - it just invokes .reduce method or coll-reduce in clojure.core.protocols


so yeah, both are in the java code - they are folds if that helps

Michael Stokley02:01:04

i have a little experience looking at folds in SICP. i remember they can often reverse collections

Michael Stokley02:01:20

maybe that's the intuition you were getting at?


that's part of it yes - a reduce can be treated as a loop that always has 1 accumulator for an arbitrary value, and one loop binding that represents "the next item" - it returns the last value of that accumulator when it gets done with the last item


@michael740 a very simple improvement you can use with your existing code is use (cons (first to-reverse) reversed) to replace your usage of concat


just wanted to point out that there are many ways to recur in clojure because of the jvm can't optimize direct recursion, and choosing which one is the aproppiate one is not that easy at the beginning, there to many variables to have in mind


no, in private, I'm newbien and may misguide you.

Michael Stokley02:01:47

cons works in "reverse" order??


equivalent is (conj reversed (first to-reverse))


compared to conj, yes, it's opposite order

Michael Stokley02:01:17

user> (cons 1 (list 2 3))
(1 2 3)

Michael Stokley02:01:35

your suggestion works but i don't see how

Michael Stokley02:01:08

cons puts the first arg in the head position. i want (first to-reverse) last


(cons x l) and (concat (list x) l) do the same thing - except cons does it more directly


no - you want it at the current head, the same way you were putting it with concat


if you add a println that shows each item you process and the current value of what you have processed so far, I think you'll see how it works

Michael Stokley02:01:56

oh. ok. i think i was still thinking about the simpler, recursively-defined function.

Michael Stokley02:01:34

where you do indeed want to return something like (cons (reversed (cdr l)) (car l))


cons has args in the opposite order though


the second arg to cons must be a collection or nil (treated as equivalent to ())

Michael Stokley02:01:32

yes, that's right.


@noisesmith in the wild, is trampoline or leftfn used much?


not as often as you might expect - they are pretty niche tools but very handy when you need them


and often they work well together


(since you want to be able to refer to other steps mutually in mutual recursion)


@noisesmith by working together you mean using trampoline inside a letfn?


I mean the should be able to return each other in order to trampoline (or use each others in partials as the case may be)


this can also be done with declare, or by passing one function to the other, but it can simplify things to use letfn


letfn alone consumes allocates stacks frames right?


it creates functions, those functions use stack, yes


Hello, could smbd please explain why in one case

(take 5 (map prn (range 10)))
REPL prints 10 numbers & in other case
(transduce (comp (take 5)
                 (map prn))
           (range 10))
it prints only 5 but we have take 5 in both examples?


I believe the first example prints 10 because of chunking. The latter doesn't chunk.

Michael Stokley06:01:01

does prn cause side effects?

Michael Stokley06:01:40

both map and range are supposed to return lazy sequences

Michael Stokley06:01:52

seems like the short answer is something like, lazy-sequences and side effects don't mix?


@michael740 yes, to that post


@michael740 😅 Yes, I got that from the article. Currently trying to understand trasreducers better. Thank you for your response)

Michael Stokley06:01:16

i hope you get a more detailed explanation. i'd be curious to know, too


For those who use compojure-api (directly or via Luminus), there is a namespace in the 2.0.0-version. Works like this:

(require '[ :as help])

;; all topics

(help/help :meta)
;; all registered handlers

(help/help :meta :path-params)
;; help on :path-params


the last on prints (with nice colors ;)):


path-params with letk. Schema is used for both coercion and api-docs.

(POST "/math/:x/:y" []
  :path-params [x :- s/Int, {y :- s/Int 1}]
  (ok {:total (+ x y)}))


hi there. how do I figure out how to integrate a flatpickr datetime-picker ( in my reagent form? I don't get how to call the flatpickr. Any help much appreciated!


clojars question. 🙂 i have a client/server project that i'm deploying to clojars via lein deploy clojars. :prep-tasks takes care of the clojurescript compilation, css is processed, etc. but when i inspect the jar that comes down from clojars it only has some content in the /public dir. most importantly it's missing my compiled javascript. any thoughts?


hmm, fixed it by adding the uberjar profile to lein deploy

Vincent Cantin13:01:11

I successfully wrote a type that prints out its content, based on bits I found in the source code of clojure.core. However, I don't fully understand the code I typed:

(deftype Node [graph id]
  (-pr-writer [this writer opts] (-write writer (str id))))
What is that -write function, and does the - prefix have a special meaning?


@vincent.cantin that’s cljs not clj

Vincent Cantin13:01:35

yes, you are right


- doesn’t have any special meaning, but it’s idiomatic to prefix a protocol method with - and then wrap it in a regular function


-write is another protocol method


Hello, maybe somebody created here osx app based on java. I need to use java to access native things. The jar run fully normal with ‘lein run’ but when I deployed with javapackager.. and start the application .. I got “application need to accept incoming network connections’. I read many java forum now.. somebody can help me, who solved this problem?

Vincent Cantin14:01:49

If I understand correctly, your app is not using the network and you want to avoid this message. Isn't it?

Vincent Cantin14:01:22

Maybe try to ask on StackOverflow.


Yes, that is the problem. I used my application as a local server and therefore I have incoming network connections.


I read about in java forums maybe that can solve with SocketLock or else.. but I don’t understand fully.


Yes, I will drop to Stackoverflow. thx! @vincent.cantin


I found out.. I signed the pkg.. but something not correct and in this case: “Such errors usually indicate broken application signature.”


I need to fix the signature

Vincent Cantin14:01:27

Just accept in the security settings of OSX.

Vincent Cantin14:01:47

That's an OSX issue, mainly.


I understand that. Just I would like to create an app for users.


Can I pre-setup something in the java or in the compiler?


Where is the best place to go to learn clojure? I’m coming from java and I’ve been struggling with learning clojure for the last 2 weeks. I’m finding the reason I’m struggling is because I don’t understand the language and some of it’s basics. It’s hard for me to understand a lot of the clojure docs as well. Are there any books, websites, articles, etc… you guys recommend to help me get up to speed?


Have you tried Eric is great in breaking the basics into digestible pieces. After trying books and tutorials, I've found his videos to work best for me.


clojure for the brave and true


also I liked this just for puzzle practice

Drew Verlee16:01:37

Living Clojure or Clojure for the brave and true. Both have a different style. If your looking for a more nuts and bolts approach, Joy of Clojure.


if you're willing to purchase pragprog has a book written written by alex miller and stu halloway. i've purchased it for myself and a coworker based on how much i enjoyed it. definitely worth the purchase price


I started with clojure for the brave and true. That fact that it was free online was great - and so I went and bought it!


Also, if you’ve done , clojure is one of the languages. It can be interesting to solve a kata in, say, java, then try it again in clojure, then once you’ve solved it, compare your solution to others and say, “Oh, ok, I didn’t know that was a thing.”


Thanks a lot guys! I’ll try all these out


i also found reading through all the stuff on great


good luck, and welcome! 🙂


oh! of course! there is this series too:, by rich hickey, the designer of clojure


there are also challanges at


Is a Java array the only option for O(1) indexed access?


vectors are very close - O(log32(n)) iirc


they have to get very large before the difference between that and O(1) is likely to matter


Yes, I know


But otherwise Java arrays. Thanks for confirming!


if a vector isn't fast enough, us an array


but do profile - it's very likely that indexed lookup is not your bottleneck


yes, of course


which tool do you profile with yourself, by the way?


free for open source right?


you can get a free license for open source use yes


Any thoughts or recommendations on an editor/IDE for Clojure? Using NightCode and Atom with some REPL support. But both are not really it. Emacs is just too intimidating… I do use VIM occasionally, but it seems a hassle to set up…


the vim setup was much easier than cider for emacs was fwiw, it's just a language mode and then optionally a lispy editing mode (I like vim-sexp) and finally fireplace if you want repl integration - fireplace is trivial to set up


I would highly recommend giving Spacemacs a try. I am a complete Emacs newbie, and after 4-5 months, I am the most productive I have ever been in any IDE/language setup


spacemacs is good but the repl kept getting in my way, I had a better time using vim + fireplace, the vim-sexp is cool and the vim-sexp-mappings-for-regular-people makes editing a breeze


spacemacs is indeed powerful but I kept getting the impression that some things were off the place


emacs or cursive


or just whatever editor and a repl


@jeroen.leenarts Is there something specific you don't like about Atom/ProtoREPL? That's what I use (I switched from Emacs).


It’s a hassle to setup… 🙂


@jeroen.leenarts if you want to avoid setup hassle, check out


Lighttable seems abandoned.


@jeroen845 Still a bit intimidating - but a lot of clojure dev are likely - and very little additional setup needed from defaults.


@jeroen.leenarts there's also a clojure extension for Visual Studio Code (great editor, haven't tried the extension though)


@jeroen.leenarts You only have to set it up once per machine and the "opinionated guide" is pretty straightforward 🙂


About a month ago I tried every option available. Vscode, atom, emacs and cursive. I’d suggest emacs with cider or cursive. Spacemacs is free and easy to install and require a little configuration. Cursive is free for studying :)


(my usual suggestion is "whatever editor you're already using" with some sort of Clojure plugin to hook into a REPL)


That last medium link seems to have worked for me… Trying atom with basic repl support now. Works much better then the “opiniated guide I used before”.


I regularly try out a bunch of IDEs and I almost always go back to Spacemacs + CIDER. Although I don’t think Spacemacs is substantially greater than any other editor. I feel like they all have certain limitations that can be annoying for certain use-cases (e.g., lack of extract-function in cursive, lack of static analysis in spacemacs — but also some static analysis can be annoying when using certain macros; such as Clara Rules rules/queries)


Really looks interesting… Emacs for my VIM fingers… Only problem is that their install from scratch is currently broken… Just my luck… 😂


They are migrating from the standard melpa package repository to their own “spacemelpa” repository.


@U7V9HE682 Any reference on that I can keep an eye on?


They fixed things. 🙂 And this looks kinda good actually.