clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Michael Gardner 2021-04-23T00:23:38.478600Z

my first inclination would be to represent the diff as plain old data, like what clojure.data/diff produces

šŸ‘ 1
Eric Auld 2021-04-23T00:41:31.478900Z

They asked for both the diff and the ā€œminimal transactionsā€, but if that is your instinct, thatā€™s informative, because maybe it means that the data is whatā€™s important, and executing it is a minor variation.

Michael Gardner 2021-04-23T00:45:44.479100Z

I don't like the way he put it, but Linus Torvalds' quote has always stuck with me:

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

šŸ‘ 1
Huahai 2021-04-23T02:09:28.479700Z

https://github.com/juji-io/editscript

šŸ‘ 1
šŸ™ 1
Huahai 2021-04-23T02:09:36.480200Z

Does that

šŸ‘ 1
craftybones 2021-04-23T06:56:17.482800Z

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ā€¦

thheller 2021-04-23T07:44:13.483200Z

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

craftybones 2021-04-23T06:56:24.483Z

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."

jumar 2021-04-23T08:20:25.486300Z

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.

šŸ‘€ 1
vemv 2021-04-23T08:30:40.487200Z

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

nilern 2021-04-23T12:49:48.490500Z

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

šŸ‘ 3
NoahTheDuke 2021-04-23T13:58:32.492500Z

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Ć³jcik 2021-04-23T15:25:04.496500Z

@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.

vncz 2021-04-23T15:47:55.498800Z

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

āœ… 1
Xarlyle0 2021-04-25T18:55:03.050500Z

Same as @markbastian except with Mount instead of Integrant.

simongray 2021-04-26T08:24:55.055300Z

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

emccue 2021-04-29T00:37:38.200400Z

Regardless Jetty seems to be the real go to

simongray 2021-04-29T06:43:07.212600Z

@emccue Honestly, any server that doesnā€™t require being independently set up is my goto when writing code. Iā€™m gonna proxy it behind nginx anyway.

p-himik 2021-04-23T15:54:12.498900Z

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

p-himik 2021-04-23T15:54:43.499100Z

FWIW, I'm using Yada.

šŸ‘ 1
vncz 2021-04-23T16:07:00.499300Z

I guess a better question would be ā€” what are the alternatives today?

seancorfield 2021-04-23T16:08:12.499500Z

@vincenz.chianese Are you asking about full stack apps or just backend web apps?

vncz 2021-04-23T16:08:33.499700Z

Iā€™m mostly interested in developing backend ā€” pure API apps

nilern 2021-04-23T16:10:02.499900Z

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

seancorfield 2021-04-23T16:10:17Z

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

seancorfield 2021-04-23T16:11:07.000200Z

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.

nilern 2021-04-23T16:11:18.000400Z

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

seancorfield 2021-04-23T16:11:24.000600Z

Pedestal always felt like overkill to me.

āž• 1
ā˜ļø 2
seancorfield 2021-04-23T16:12:24.000900Z

@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 šŸ™‚

emccue 2021-04-23T16:14:48.001100Z

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

nilern 2021-04-23T16:15:14.001300Z

Reitit has interceptors too šŸ˜œ

mpenet 2021-04-23T16:18:52.001600Z

You can use any interceptor lib with plain ring

borkdude 2021-04-23T16:19:07.001900Z

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

vncz 2021-04-23T16:19:40.002200Z

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

vncz 2021-04-23T16:20:12.002400Z

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

mpenet 2021-04-23T16:20:16.002600Z

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

mpenet 2021-04-23T16:20:32.002800Z

But maybe nowadays it's less of a thing

vncz 2021-04-23T16:20:44.003Z

Not something that iā€™m particularly interested but I see the point

nilern 2021-04-23T16:32:04.003200Z

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

nilern 2021-04-23T16:35:08.003700Z

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

athomasoriginal 2021-04-23T16:35:24.004Z

Reitit, ring-jetty

ghadi 2021-04-23T19:53:05.006200Z

we use pedestal at Nubank & Cognitect

2021-04-23T19:57:04.006400Z

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.