This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-09
Channels
- # babashka (63)
- # beginners (97)
- # biff (11)
- # chlorine-clover (5)
- # cider (46)
- # clara (2)
- # clj-kondo (34)
- # clojure (65)
- # clojure-austin (1)
- # clojure-europe (9)
- # clojure-france (10)
- # clojure-italy (11)
- # clojure-nl (3)
- # clojure-spec (29)
- # clojure-uk (5)
- # clojuredesign-podcast (1)
- # clojurescript (56)
- # clr (6)
- # component (17)
- # conjure (5)
- # core-typed (5)
- # cursive (23)
- # data-science (5)
- # datahike (3)
- # dirac (3)
- # emacs (20)
- # fulcro (17)
- # graalvm (10)
- # graphql (8)
- # helix (99)
- # honeysql (7)
- # jobs-discuss (9)
- # juxt (9)
- # leiningen (14)
- # malli (3)
- # meander (6)
- # off-topic (77)
- # pathom (7)
- # re-frame (12)
- # reagent (8)
- # reitit (10)
- # restql (1)
- # shadow-cljs (22)
- # spacemacs (10)
Let’s say I have two actors (loosely defined: just individual pieces of code, running async with regards to each other) whose job it is to take a value, assign it a key, and store it locally (to each actor) in a map. It’s unimportant what the key is (but we’re interested in avoiding collisions). They have read access to each others’ maps, but write access to their own map only. They would like to do their work with minimal coordination. Is it possible to get the two actors to reliably assign the same key for the same value such that when a value is present in both of them, they have identical keys? (This is a thought experiment)
You can either have a coordinated storage where you explicitly store a value-key map that both actors use and update, or you can have a function that always generates the same key if given the same value. I can't think of any other alternative.
Yeah, the first would be useful if the storage is faster at processing values than the actors (they could then saturate the storage). If it’s not fast, you might just as well just use one actor. Hashing the value seems straightforward, but you’d have to deal explicitly with collisions I guess. A third that occurred to me (although it’s probably a bad idea in practice) is to coordinate when a value is new, but not when it’s known. I.e., when a value that’s not present in either map appears, they have to access some shared resource and stop the other from trying to write the same value at the same time. Essentially a kind of mutex, I guess.
I’m guessing I should read up on https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type and not Central Regional Dental Testing Service.
the other technique that’s usually contrasted with CRDTs is Operational Transforms, but CRDTs seems much easier to work with
What is the word for something that handles dependencies?
what kind of "handling"?
I suppose it would be enough here to express that it holds a set of things and tracks their dependencies. I think trying to go for one word here probably isnt helpful 🙂
Write a Slack bot for this http://maxgfeller.com/javaclassnamegenerator/
I typed in "something that handles dependencies" and got "InitializerProxyManagementInitializerServlet"
There seem to be a surprising shortcoming in Clojure routing libraries. They either do not support reverse routing, or claim to support it but make near impossible to use because they require the routes map which cause circular dependency.
Here is another person facing the same dilemma : https://www.reddit.com/r/Clojure/comments/gz3o7m/common_circular_dependency_issue/
can’t the router add any necessary info for parameterized hrefs to the request? doing so would allow views to be pure functions of the request
You can also use a layer of indirection by using a keyword to identify routes instead of routing by value.
> That's what yada/bidi do Can you please elaborate? The only thing pertaining to the URL I see is the uri and the query string
> You can also use a layer of indirection by using a keyword to identify routes instead of routing by value. That doesn't seem to be possible without some twisted promise/deliver: https://github.com/juxt/bidi/blob/master/doc/patterns.md
I still don’t understand why views must require the routes. seems like any of the circular dependencies can be handled with middleware, which live in the routes file
@U7RJTCH6J bidi reverse route function requires the routes map: (path-for route :index)
can’t middleware at the route information to the request to make it available for the view?
@U7RJTCH6J worked like a charm 🙏 - I was under the assumption that request middleware are for associating headers only


middleware can be a bit tricky, but it’s a fairly powerful, flexible tool
@UAX4V32SZ patterns have nothing to do with what I'm talking about. If you have a route map in bidi, you can use keywords as handlers. Then you can match a route to the keyword, then pick which handler to call based on that. When handlers want to generate a url, they can find it by looking for the keyword.
@U09LZR36F I was just trying this without success.
(ns myproj.handler
(:require [bidi.ring :refer (make-handler)]
[myproj.site.handler :refer [home-handler not-found-handler]]
[myproj.account.sign-in :refer [handler] :rename {handler sign-in-handler}]))
(defn make-handlers []
{;; Site
:home home-handler
;; Account
:sign-in sign-in-handler
;; Other
:not-found not-found-handler})
(defn make-routes [handlers]
["/" {;; Site
"" (:home handlers)
[[#"[a-z]{2}" :lang]] (:home handlers)
;; Account
"account/" {"sign-in" (:sign-in handlers)}}])
(def routes
(make-routes (make-handlers)))
(def handler
(make-handler routes))
@U09LZR36F (prn) the context/request explains the problem but I am not sure how to solve it: {:routes {:home #object[myproj.site.handler$home_handler 0x24435620 ... the functions are resolved before reaching my views
Unless I must return the promise and deliver it in my views as explained in doc/patterns.md?
The promise thing also works, but it's really just a way to do circular dependencies
Fwiw, if you use bidi with yada, yada will give you functions like yada/uri-info to solve this problem.
I’m not familiar with bidi or yada, but I was thinking of just wrapping your routes with some middleware similar to the following:
(defn wrap-path-for [handler]
(fn [request]
(let [request-path-for (partial path-for routes)]
(handler (assoc request :path-for request-path-for)))))
your handlers can then just grab path-for from the request:
(let [path-for (:path-for request)
my-path (path-for :index)]
...
)
But if you hand roll it, you're designing a custom system and you have no docs, etc
@U09LZR36F I am using Liberator never tried yada. Is it better?
> make-routes should use references to the keywords Can you elaborate on this. I don't get it 😞
(def routes ["/" {;; Site
"" :home
;; Account
"account/" {"sign-in" :sign-in}
;; Other
true :not-found}])
How bidi will know which function to use for routes in such case?Thanks for all the help @U09LZR36F & @U7RJTCH6J - I have the desired result now; routing via keywords

Thanks - I am doing that now by passing it to the middleware and destructure the request
Your code has a static structure, the way it is arranged on disk in files that declare namespaces, and that static structure builds the dynamic structure which is the program actually running
If you run into that wall, something to consider is: should/could this be passed as argument at runtime(dynamic dependency) instead of depending on a global def(static/know at compile time)
This is one of the reasons I prefer component to mount, mount tries really hard to force the dynamic structure of your program to match the static structure of your code, which encourages depending on globals instead of passing arguments
All of the frameworks for lifecycle management/dependency injection can be abused. Write your start/stop functions first, as if you don't know which framework you are going to work with and it doesn't matter which you choose. They become interchangeable and you make sure you don't end up with spaghetti dependencies
This isn't abuse, the core mechanism mount uses to structure dependencies is vars in namespaces in files, so mount dependencies are tied directly to the static structure of your code
That's true, but you don't have to relate to them as globals. If you wrote your application without the knowledge that your dependencies are global, then your only option would be to pass them to your start function as an argument. So in practice your lifecycle function isn't aware that it's receiving a global variable. It just knows its receiving data or a protocol and can work with them the same as if they were global or not
The mere fact that your routes are def'ed as global turns it into a cyclic dependency if you try to require the namespace they are def'ed in in a namespace that defines a handler, which you need if you want to use reverse routing features
Just speaking to component vs mount. Would need to see an example of reverse routing. I admittedly don't understand the problem well but I usually work with this approach and I haven't encountered a situation in which it didn't work out
I would encourage you to take another look at component. At it's core it is very little. https://gist.github.com/hiredman/075b45eaeb01e4b526ce6f8854685487 contains all the functionality of component in 30 lines of code, the difference between that and the actual component library is ease of use and better error messages
> That's true, but you don't have to relate to them as globals. As soon as you have globals and the code is shared between workers there is a high chance someone comes along and uses the globals directly, for whatever reason. It's just like teaching a kid to not drink that bleach vs not buying bleach in the first place, where the latter options is a safe route to make sure your kid never ever drinks bleach.
If you really stretch your imagination, you can imagine writing map anew for every different function you are mapping instead of passing in a function, so like maybe there is a single namespace(M) full of different map functions. And you have another namespace(X) that defines some cool function (F) and you want it able to map it, so you make M require X and define a new mapping function in M that calls F on each item in a collection. Now F can't use M without it being a circular dependency.