Fork me on GitHub
#clojure
<
2021-04-23
>
craftybones06:04:17

I’m messing around with clojure.java.classpath . If I require it in a lein repl and call the clojure.java.classpath/classpath fn, I get an empty list. I would expect to see something at least…

thheller07:04:13

make sure you have a version that actually supports JDK9+, older versions only work up to JDK8

craftybones06:04:24

the documentation says:

"Returns a sequence of File objects of the elements on the
  classpath. Defaults to searching for instances of
  java.net.URLClassLoader in the classloader hierarchy above
  clojure.lang.RT/baseLoader or the given classloader. If no
  URLClassloader can be found, as on Java 9, falls back to the
  'java.class'path' system property."

jumar08:04:25

In Joy of Clojure, 2nd ed p. 450 they say: > Using dynamic binding is the preferred way to handle recoverable errors in a context-sensitive manner. They also say on p. 447 that > In its purest form, dynamic binding is a structured form of a side effect. The example they show is something like this: https://github.com/jumarko/clojure-experiments/blob/master/src/clojure_experiments/books/joy_of_clojure/ch17_clojure_way_of_thinking.clj#L474-L517

(defn ^:dynamic handle-weird-animal
  [{[name] :content}]
  (throw (Exception. (str name " must be 'dealt with'"))))
...
(defmethod visit :animal [{[name] :content :as animal}]
  (case name
    ;; Note: could be `cond` and use `#{"Spot" "Lopshire"}
    "Spot" (handle-weird-animal animal)
    "Lopshire" (handle-weird-animal animal)
    (println name)))

;; the default error handling
(traverse DB visit)
;; 1. Unhandled java.lang.Exception
;;     Spot must be 'dealt with'

;; custom error handling
(binding [handle-weird-animal (fn [{[name] :content}] (println name "is harmless"))]
  (traverse DB visit))
Is this something that people actually use as a standard practice? I tend to frown at dynamic binding because it's implicit rather than explicit and can lead to unpleasant surprises.

👀 3
vemv08:04:40

Yeah a defn that throws exeptions unconditionally by default sounds like a defprotocol/defmulti in disguise

nilern12:04:48

That is an idiom you can use to emulate Common Lisp -style conditions and restarts but I haven't seen it actually used And I avoid dynamic binding in general because it is bound to the low-level thread abstraction so it breaks in the presence of fancy thread pooling like core.async and even just lazy seqs

👍 9
NoahTheDuke13:04:32

If you're looking for an actual implementation of Common Lisp's condition system, check out https://github.com/IGJoshua/farolero, which uses dynamic bindings

Karol Wójcik15:04:04

@nilern point is just right! I’m working with dynamic binding (async context) in conjuction with core async on daily basis and it’s one big hack which I wish to get rid of someday.

vncz15:04:55

Stupid question: is Pedestal still the go-to choice for web applications? I had a good experience with it so far but wondering if people are using something different nowadays

3
p-himik15:04:12

I wouldn't say that there even is the go-to choice for web applications. There are many choices.

p-himik15:04:43

FWIW, I'm using Yada.

👍 3
vncz16:04:00

I guess a better question would be — what are the alternatives today?

seancorfield16:04:12

@U015VUATAVC Are you asking about full stack apps or just backend web apps?

vncz16:04:33

I’m mostly interested in developing backend — pure API apps

nilern16:04:02

At Metosin the go-to stack was Ring + Reitit and it is in the new Web Development with Clojure book too

seancorfield16:04:17

I think most folks just go for compojure-api for backend API apps?

seancorfield16:04:07

At work we don’t even use compojure-api — just plain ol’ Ring + Compojure, although we also have a GraphQL app. And one app uses Bidi instead of Compojure.

nilern16:04:18

Nobody wants to maintain compojure-api, definitely prefer Reitit for new apps

seancorfield16:04:24

Pedestal always felt like overkill to me.

3
☝️ 5
seancorfield16:04:24

@nilern Yeah, that’s def. the impression I’ve been getting too. I think I would try Reitit for any new web apps I wrote at this point. But compojure-api is def. “popular” still 🙂

emccue16:04:48

I like pedestal - its docs could use some love and probably some parts of it could use a decoupling, but the interceptor thing is overhead i like the moment i want to do websockets

nilern16:04:14

Reitit has interceptors too 😜

mpenet16:04:52

You can use any interceptor lib with plain ring

borkdude16:04:07

I still like yada but it's not very actively maintained. Still, it has what I need, including swagger and async

vncz16:04:40

What I do not like about Pedestal so far (I know that’s stupid) is the fact they ask for a :route-name that really feels useless

vncz16:04:12

Other than that, I do not have any particular complains — I was mostly interested in alternatives

mpenet16:04:16

It's useful for reverse routing in theory, like from templates

mpenet16:04:32

But maybe nowadays it's less of a thing

vncz16:04:44

Not something that i’m particularly interested but I see the point

nilern16:04:04

On frontend reverse routing is more often useful but also on the backend good to have for redirections at least

nilern16:04:08

Of course if you don't make a SPA then all that link generation moves to the backend as well

athomasoriginal16:04:24

Reitit, ring-jetty

ghadi19:04:05

we use pedestal at Nubank & Cognitect

markbastian19:04:04

The main lib combo I use for webapps these days is integrant (system composition) + http-kit (server) +ring (server abstraction) +reitit (routing). I’m very happy with it.

Xarlyle018:04:03

Same as @U0JUR9FPH except with Mount instead of Integrant.

simongray08:04:55

Pedestal is pretty great and I like how the server part is integrated (if you use jetty).

emccue00:04:38

Regardless Jetty seems to be the real go to