Fork me on GitHub

so after friend, and then buddy, is there a new/actively maintained webb security library?


I do not know, not having used such libraries, but do friend and/or buddy still work? Some libraries in Clojure are stable and working, even if they haven't been changed in a while.


yeah I still have an app in production with friend


I think one can also make use of Apache Shiro directly:

Arto Kalishian05:10:34

I am learning Clojure and would like to know if I am the right track from experienced developers who preceded me in their learning path. So far what I accomplished is: 1. Studying all the basics of Clojure Language from different sources like Clj for brave true.. & Quick Clojure (awesome book btw). 2. Learn all the basics of Clojurescript from a web dev ebook. 3. Tried to delve into Fulcro and studied until 3.8 but could not continue for several reasons not relative to mention here. 4. Studied Luminus framework, liking it from Web Dev 2nd edition book. But I realized that I am still not so good with Clojure basics so went back to revise before I continue. What I meant to say that my learning style is coming back and forth a lot and is very dynamic. I wonder if this is how most of you learned and if there is a more efficient way to learn through practice for example to know the best practices. Highly appreciated.


I learned enough of the basics to get going, did some 4Clojure, then landed a job writing Clojure. I personally don't think there's much point in reading up too much unless you actually intend to use the language - either for a hobby project, or in production. So my suggestion would be to do just that - if you like the language, find a way to use it "in anger", the rest of the learning will follow. Books will only take you so far.

๐Ÿ‘ 4
โž• 4

Agree with @sgerguri - Iโ€™m writing a cljs frontend for my company and just seeing how it works out.


Learning from books is fine but I only really learn when trying to build something, preferably on a deadline..

๐Ÿ‘ 4
โž• 4

Going through exercised can help with getting acquainted learning the basic functions, doing things like loops, conditions, manipulating data-structures etc.


Books can help with overall application design hints. But like other said, practice makes perfect


I think doing a lot of coming back and forth is normal and good for learning

๐Ÿ‘ 4

I definitely did a lot of it.

Arto Kalishian08:10:41

Thank you a lot for all the advice. Really helps. I'll definitely try 4clojure and yes I have project in mind. Is there a way to work for any company over seas for free through assignments?


That's one other thing I wouldn't do either. Build a project of your own, or extend something that you're using already. Better yet, find a place where you can sneak Clojure in at your current place - there's bound to be some scope for an internal miniproject where nobody will honestly care what technology you're using as it's not going to be critical for project delivery. Build support and excitement for the language, run learning groups, etc. It's a lot easier (and better in the long term) to try and build support for something you care about where you are than trying to jump through hoops to land something remote overseas.

๐Ÿ‘ 12

quick questions about clojure.datafy/nav. the first argument coll is the result of the previous clojure.datafy/datafy right? not original object passed to datafy?


wondering if I should implement nav on the original object or via metadata on the datafy result


Given a system that is already happily configured for logging using a combination of logback and slf4j, have folks found any compelling reasons to migrate to using timbre?


the words "happily" "logging" "logback" "slf4j" are so rare in one phrase that i would keep stuff like they are ๐Ÿ˜„


Well, happiness is a subjective thing...


After running multiple (15+) Clojure apps in production I found that what happens with logs after they're being produced is way more important, how you log is a secondary concern ๐Ÿ˜‰ We use tools.logging + logback with a custom formatter and MDC in few places and it doesn't feel like we need to change anything. What would be your reason for migrating to timbre if current setup is working?


We thought Timbre looked like a great idea and used it for several years @kelveden but we recently migrated our entire code base (back) to tools.logging, log4j2, and its various bridges/adapters. There's a lot to be said in favor of industry standard logging...


We have pretty much the exact same setup as @U0JEFEZH6.


timbre is really horrible if you want more customized log message and really easy for things like changing log level dynamically at runtime (which is much harder with tools.logging & log4j2)


Thanks for the thoughts guys, really interesting. It confirms my gut instinct: if it ain't broke don't fix it, particularly when it is a tried and tested stack used across the industry.

Arto Kalishian10:10:46

Doesn't the as-> macro make clojure's immutability strength pointless?


you didn't mutate anything there @UNQ70RULA - you just rebound foo


here's the macroexpansion of your expression:


(let* [foo 1 foo (inc foo)] (println foo))

Arto Kalishian10:10:33

You mean we over written foo's value so in that case it's not considered mutation because it was on purpose?


it's not mutation - you are effectively creating a new foo which shadows the old one, but you aren't mutating any values. if the value of the original foo was stored anywhere, it is not changed by the inc

๐Ÿ‘ 4

Is the above screenshot from some sort of tutorial? That looks very misleading for beginners

Arto Kalishian11:10:59

Quick Clojure book

Arto Kalishian11:10:02

I'm still confused a bit but telling myself perhaps when I practice it will be more clear.


hmm, I'm not sure how good a reference that book is.. from the chapter previews it looks like it's written from quite an imperative standpoint


does this make it any clearer @UNQ70RULA

(let [bar-a (atom nil)]
  (as-> 1 foo
    (reset! bar-a foo)
    (inc foo)
    (println foo))
  (println @bar-a))
;; 2
;; 1
;; nil

Arto Kalishian11:10:42

I like it to be honest because it attempts to be concise whereas most books try to be comprehensive which is not a good start for beginners.


The chaper on "Sequences" starts off by introducing doseq and saying looping over collections to carry out side effects is a common task in Clojure ๐Ÿ˜ฆ


(that is definitely not the case)

Arto Kalishian11:10:47

Thanks Craig. Yes it does. But in the first example we printed foo's shadow =2... is that considered still safe to use in any app without risk of a value changing without our consent? In other words is it safe to use as-> or it makes an app less safe?

Arto Kalishian11:10:36

@UCPS050BV I'm surprised since this book is probably the most recent of all my collection being in 2017... most other books are probably 2015-16

Arto Kalishian11:10:19

Or maybe to rephrase @U0524B4UW... isn't it safer to create a new variable to assign it the increment or that's pointless?


@UNQ70RULA it's still safe - as-> isn't doing anything special, it's just saving you the work of writing some let bindings and hopefully making the intent of your code easier to divine... (although, that said, i rarely use as->)

๐Ÿ‘ 4

you certainly can create a new variable to assign the increment, but that has its own difficulties (it's very easy to accidentally refer to the un-incremented variable in later code, especially after some refactoring)

๐Ÿ‘ 4
Arto Kalishian11:10:36

Nice thoughts ๐Ÿ‘

Arto Kalishian11:10:24

I remember when i learned some rust they used a similar concept of shadowing rather than creating a new variable.

๐Ÿ‘ 4

i generally prefer the thread macros which don't bind a variable... -> and ->> - there are no such issues with them

๐Ÿ‘ 4

that may just be my personal preference though

Arto Kalishian11:10:26

I make thumbs up it disappears for some reason... ๐Ÿ˜„


Another issue I'd have with that example is that as-> is designed to be used inside -> hence the "odd" argument order.


I hadn't heard of Quick Clojure but based on this thread I think I would recommend avoiding it.

Arto Kalishian15:10:33

Maybe "avoiding immutability" was just misplaced and it can improve in next book version. To be honest the rest of the book was enjoyable so far..


I'd never heard of that author. Searching for his name and Clojure only yields that book so it's hard to tell his credentials. There are certainly bad Clojure books out there. Enjoyable != good, necessarily ๐Ÿ˜

Arto Kalishian15:10:45

I have posted the complete section where he mentioned the as-> macro for fairness

Arto Kalishian15:10:06

The reason I also included this is to be clear that the author used as-> to avoid the alternative complicated version he mentions.


That's pretty horrible stuff. Now I'll definitely recommend people avoid that book!

Arto Kalishian15:10:03

Glad to have your opinion about this to be aware.

Arto Kalishian15:10:31

I thought Apress are selective.


He's coming at this from completely the wrong angle -- and the comment about doseq in the sequences chapter confirms that.


Apress is better than Packt but...

Arto Kalishian15:10:58

So if you recommend 3 books for beginners... what they'd be?


A lot of these publishers churn out books just so they have something in a given section.


Living Clojure and Getting Clojure are probably the first two that come to mind. When I'm at my desk I can be more sure if that.

๐Ÿ‘ 4
Alex Miller (Clojure team)15:10:45

I skimmed through some examples on amazon and I agree with Sean. This is a badly written book (as is common with many Packt books)

Alex Miller (Clojure team)15:10:32

I concur with Sean's recs, or Clojure for the Brave and True, or Programming Clojure

๐Ÿ‘ 4
Alex Miller (Clojure team)15:10:04

(I am a co-author of the last so I am biased here :)

Arto Kalishian15:10:22

My only concern that books published in 2015.. 4 years passed. Probably back then clojure was 1.7? Some things changed right?


A good old book is better than a bad new book.

๐Ÿ™‚ 4
Alex Miller (Clojure team)15:10:27

Clojure changes slowly enough that it really doesn't matter much


Clojure changes fairly slowly, by design. A few things that have been added are important, but a lot of Clojure 1.3/1.4 era advice is still good.


Transducers (1.7), Spec (1.9), the new CLI/`deps.edn` (1.10). Those are important additions, but the core is very similar.


I would avoid anything that was based on 1.2 tho' since the Contrib libraries went through a massive change between 1.2 and 1.3.

Alex Miller (Clojure team)15:10:19

clj/deps was actually 1.9

seancorfield15:10:25 gives a good sense of what has changed in each version. It's almost always pure additive and very stable (it's why we've run alpha/beta builds in production since Clojure 1.3).

Alex Miller (Clojure team)15:10:44

Programming Clojure is based on Clojure 1.9 and includes spec, clj, etc


Ah, it isn't listed in the changes log (which makes sense) so I was just trying to put "large" features into release buckets ๐Ÿ™‚

Alex Miller (Clojure team)15:10:22

Getting Clojure is either 1.8/1.9 era, can't remember

Alex Miller (Clojure team)15:10:32

Living Clojure is 1.6 era

Alex Miller (Clojure team)15:10:09

Clojure for the Brave and True is probably similar, can't remember

Arto Kalishian10:10:48

Or maybe there is something not clear for me?

Arto Kalishian10:10:46

I mean if we're going to work around it anyway we might as well use javascript or java... no?


@thheller i think @seancorfield and/or @lilactown should be able to answer your question about datafy/nav if you haven't gotten an answer already


shortly after I asked I realized that next.jdbc had support for this so I just looked there. so yeah it is the result of datafy not the original value


@thheller I wrote a blog post about the principles behind datafy/`nav` that might help...


oh nice. must have missed that before. thx.

Arto Kalishian13:10:19

Guys, is there any book for clojure app design patterns?


elements of clojure from Zach Tellman is wonderful book too

โค๏ธ 8

We thought Timbre looked like a great idea and used it for several years @kelveden but we recently migrated our entire code base (back) to tools.logging, log4j2, and its various bridges/adapters. There's a lot to be said in favor of industry standard logging...


Another issue I'd have with that example is that as-> is designed to be used inside -> hence the "odd" argument order.


ah. reading it its not avoiding the immutability as much as avoiding bindings. Ie, you don't have to name things if you thread it through


which book is this one?


It's definitely poor wording (and that can be seen in previews for other chapters too).

Ben Hammond15:10:21

are the bindings in a let clause guaranteed to be evaluated in lexical order? If I write something like

(let [start-time (java-time/local-time)
      result (do-really-long-computation)
      finish-time (java-time/local-time)]
  {:start-time start-time
   :result result
   :finish-time finish-time
   :elapsed-secs (java-time/as (java-time/duration start-time finish-time) :seconds)})
might I sometimes get a nasty surprise with the measurements?


yes. no.

๐Ÿ‘ 4

longer explanation: clojure isnโ€™t lazily evaluated and you can refer to the letโ€™s defined above the one youโ€™re currently defining so it couldnโ€™t work another way


You could get a nasty surprise if do-really-long-computation returned a lazy sequence very quickly, and that wasn't what you expected to be measuring.

๐Ÿ‘ 8

is there a way to configure prn to print 'foo instead of (quote foo)?


โœ” ๎‚ฐ clj
Clojure 1.10.0
user=> (prn 'foo)


where do you get (quote foo) from?


(prn (quote (quote foo))) or (prn (read-string โ€œโ€™fooโ€)) I actually want to print a quoted foo not a foo


Hi Clojurians, what is your favorite library for authentication? A friend wants to use Pedestal with something fairly out-of-the-box friendly


I am aware of Buddy, but I don't know much about the current sample size, so I figured I'd ask. Danke.


I think buddy is the most comprehensive and most used


how many deps does buddy drag along ? ๐Ÿ™‚


I would scrutinize the cryptographic routines very closely


uhh, just checked, bouncy castle, cheshire, jackson ... this stuff is heavy ๐Ÿ™‚


what alternative do you suggest?


I think the auth/z stuff in it is well-done, but would consider using something very simple and hard to mess up for encryption


like libsodium / NaCl designs -- or something that doesn't give you knobs


@vincent493 i think it depends on the problem i'd have to solve ๐Ÿ™‚


no algorithmic selection of JWT signing algos


authentication for a basic json api?


if you dont care about client cpu time - jwt is perfectly fine


with a public-private key algo like rsa


jjwt has gone nicely modular recently , so you can ship your own lightweight json engine instead of jackson ... and use the crypto stuff from within jdk itself. works pretty ok in my experience with rsa and even some ec keys


ec is quite a wild zoo though ๐Ÿ™‚


But the original question posed stated: > A friend wants to use Pedestal with something fairly out-of-the-box friendly


Remind me to never ask a clojurian to recommend me a car stereo

๐Ÿ‘Ž 4

buddy certainly sounds like it gets you going quickly ๐Ÿ™‚


because we will absolutely end up talking about wheel design


well ... i think some stuff is on the other end of the spectre


a person needs a wheel to turn some wheels and we tend to give them the whole carfactory


buddy people already have made some stuff modular, i hope they continue their path and make some light-weight setup possible too


i don't think people have to do everything by hand, but nicely modular things are better ๐Ÿ™‚ (and i wouldn't touch clojure with a stick if it'd tell me to install scala runtime, half of apache spark and spring boot just to make it bring up a repl)


in a weird way i hope clojure core parts will remain as they are. the weight feels just about right.


Iโ€™m just becoming skeptical of whether I could ever take clojure seriously for something I care about. Modular is nice, but back to cars โ€” I still prefer to just buy a car rather than build one myself from spare parts. I have other things to do


yes of course, you should be able get a car that just works


but if you pull in jackson - that thing alone is bigger than clojure


and bouncycastle is even bigger and you will likely use 5% of it or less


which is especially weird if your jdk supports the needed crypto parts out of the box


itโ€™s a shame there isnโ€™t a better alternative in place by now


how long have people been building web apps with clojure now?


well if buddy guys could make you choose between jackson and data.json for start


this is basic stuff


this would be nice, no ?


i only do data processing with clojure, no webapps. (those in my architecture are plain boring old java, sorry)


lol someone thumbed me down above


I donโ€™t think being sarcastic about people making a best effort to give helpful advice is good behaviour

โœ”๏ธ 8

even if you disagree with their advice


many of these topics are the ones where even disagree with ourselves ๐Ÿ˜„


Iโ€™m not being sarcastic at all. I thought we were having a nice conversation. Sorry if I offended you @kulminaator. Iโ€™ve been very interested in what you have had to say


you didn't offend me ๐Ÿ™‚


i think this is a healthy discussion


thank you I thought so too


people want lightweight tooling . lightweight for usage patterns (when you just start out) and lightweight to own (which you get to once you have piled up all possible deps for years)


So do you have any thoughts about why a lightweight library doesnโ€™t yet exist in clojure for such a common need?


i'm not sure. i don't even think adding another library will improve things much. it would be better if people motivated would get involved in slicing up buddy more ๐Ÿ™‚


if you look at rubygems and npm world ... having 5 libraries too many for a problem hasn't really solved issues


my guess: crypto is scary, the java libs are very mature and well maintained if clunky, so people just use the clunky java libs

๐Ÿ‘ 4

i have a ruby project around here that depends on about 100 open source libraries "collected" 10-5 years ago


you can only shiver thinking about how many of those are still properly maintained


crypto is somewhat scary yes. messing up is very easy to do.


The README for buddy says that it has 4 independently-usable parts. I haven't used it, but perhaps that split already helps avoid unnecessary dependencies, if you figure out which one part you want to use?


but then again, if you pull in jackson which has had a handful of remote code execution issues over the last 2 years ... uh oh ๐Ÿ˜ž


ooh that is scary


andy the ones i mentioned were in buddy-core


i didn't even look into the other ones


thumbs up to cheshire people at least that they bumped up their jackson dependency with the security updates released to jackson :thumbsup:


Well, again thanks for your thoughts on this @kulminaator. Itโ€™s very helpful to hear about this from the perspective of somebody with much more experience


what library doesn't exist? for auth and security?


We ended up using the Apache OLTU stuff (including jose.jws) for our OAuth-based auth/security stuff. It seemed simpler than either Buddy or Friend, TBH, but the docs are pretty poor.

Lone Ranger18:10:57

Speaking of which, I'm implementing an OpenID/Oauth2.0 compliant identity server (ring/datomic w00t!) Does anyone have any good identity server projects to point to (any language really, but preferably Clojure)


@goomba Let me know if you find any -- that was the hardest part for us. There seem to be lots of libraries for OAuth2 clients but almost nothing for servers (which is why we eventually settled on Apache OLTU).

Lone Ranger18:10:23

I'm not really seeing anything, but if I get it figured out I'll do a writeup.

Lone Ranger18:10:40

More security on the web is better!


@goomba I came from Ping Identity where we had a OIDC/Oauth2 server product. There is quite a bit of work involved here but you probably donโ€™t need all the features we incorporated. I am happy to look at a writeup of requirements if you like.

Lone Ranger19:10:05

I'll message you ๐Ÿ™‚


The source code for OLTU and the RFC spec for OAuth2 processes were our guide ๐Ÿ™‚


(so we ended up with separate Auth, Login, and API services based on that)

Lone Ranger19:10:49

10-4... I'll take a look!

Arto Kalishian19:10:11 is so much fun, thanks to whoever who built it!

๐Ÿ‘ 8

amalloy hangs out on freenode irc #clojure, I'll pass that along

๐Ÿ‘ 8

he's also the one behind flatland/useful which is a good example of clojure code style and a good utility lib


oh it moved but google knows where it moved

โค๏ธ 4
Arto Kalishian19:10:38

So in what way are these functions useful?

Arto Kalishian19:10:28

Like in large projects?


I believe in general they are things that the author found generally useful across multiple projects they worked on, similar to how many functions in clojure.core are generally useful.


In much the same way we found several "almost-core" functions to be useful enough to put them in a library:

Arto Kalishian19:10:34

Perfect, Bookmarked!

Arto Kalishian19:10:15

The beauty of such extensions seems to reduce / compress lots of boilerplate code.

Arto Kalishian19:10:28

1 line replace 20...


@seancorfield it looks like apache OLTU is also marked as retired (is this some sort of trend), did the implementation get picked up somewhere else?


@clypto Good question! I haven't checked to see if it was superseded by something else or just moved elsewhere. Finding the basis of an OAuth2 server setup was hard so I hope there is still a version of it or an alternative somewhere that is well-maintained ๐Ÿ˜

Space Guy20:10:11

We use Keycloak (Red Hat, Java) as an identity server, then our application sends users through it as an OpenID 'redirect flow' and talks to it as an OpenID API client


interesting, it looks like Keycloak is robust - at least with identity brokering, and account federation

Space Guy20:10:33

Right, that's why we wanted it - it means we don't have to build 'either user/password, or SSO via this SAML server' or other stuff like 'configure password restrictions' in the main application

Space Guy20:10:26

In the application side we're using a Java library "Nimbus Oauth 2.0" to parse requests/make response URIs - just implements the spec/JWT/JSON, track your own state

Space Guy20:10:52

Both of those are open source - I've read bits of Keycloak source to see what's going on


thanks - that's very helpful, I wasn't aware of either of those