This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (39)
- # architecture (9)
- # aws (2)
- # babashka (17)
- # beginners (73)
- # calva (6)
- # cider (27)
- # clj-kondo (140)
- # cljdoc (67)
- # cljsrn (1)
- # clojure (99)
- # clojure-dev (4)
- # clojure-europe (35)
- # clojure-nl (7)
- # clojure-spec (19)
- # clojure-uk (2)
- # clojurescript (40)
- # community-development (3)
- # cursive (10)
- # datalevin (2)
- # datavis (2)
- # datomic (27)
- # deps-new (5)
- # events (2)
- # fulcro (38)
- # integrant (6)
- # jobs (3)
- # keyboards (1)
- # leiningen (13)
- # lsp (3)
- # malli (10)
- # meander (5)
- # membrane (1)
- # membrane-term (9)
- # missionary (3)
- # off-topic (29)
- # polylith (3)
- # reagent (3)
- # reitit (5)
- # remote-jobs (2)
- # reveal (7)
- # shadow-cljs (20)
- # tools-build (4)
- # tools-deps (8)
- # vim (10)
- # xtdb (3)
any recommendations on books for programming systems with many simultaneous threads?
the cheeky recommendation that Alan Kay gives for designers of distributed systems is https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4691023/, a textbook so massive that it is sold in looseleaf so readers can bind it themselves into separate binders. his argument for it is that the only systems in nature that have successfully scaled to billions of components are biological systems, so we need to learn from them.
My code is off by one, and I cant figure out why: https://github.com/christiaan-janssen/advent2015/blob/master/src/day_01.clj The correct awnser is 74, but I get 73
Might your input contain (possibly non-printable) characters other than "(" and ")"?
My suggestion would be to check the sequence of values that floor takes on problematic input.
The code is below - I have to create objects and deal with a promise:
const template = await Template.fromDirectory('./test/data/latedeliveryandpenalty') ;
// load the DSL text for the template
const testLatePenaltyInput = fs.readFileSync (path.resolve(__dirname, 'text/', 'sample.md'), 'utf8') ;
const clause = new Clause (template) ;
clause.*parse* (testLatePenaltyInput) ;
// get the JSON object created from the parse
const data = clause.*getData ()*;
I am integrating aws redis cache in my clojure code, Can anyone help me in this? Any documentation and which library to be used ?
the readme is pretty thorough. the carmine api matches the redis commands, so
redis GET, etc so if you know what you want to do in redis, translating into carmine code is pretty simple
i use http://grep.app to search for examples. https://grep.app/search?q=taoensso.carmine%20%3Aas
@U02EA2T7FEH.. I never configured aws earlier... Sorry to ask such questions.. but how it is configured in clojure? I see python example https://github.com/aws-samples/amazon-elasticache-samples/blob/f12935d1f3427a3958550749e38e62f039d6f619/database-caching/example.py#L42
here’s the full connection spec that i’d suggest using https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine.clj#L31
Is there a flavor of
let which will return the final binding if there is no body? If the bindings are just a data pipeline
->> does a great job, but
let is often seen with the only body expression simply being the terminal binding which feels like it breaks the flow in what seems to be a very common case. Or perhaps I’m thinking about things the wrong way?
Yes, that occurred to me, and is better than simple repetition, but it also breaks out of the structure of the
let binding block for no reason other than syntax constraints. I realize it is a small thing, and perhaps my aesthetic sense is overly tuned to appreciate consistency/regularity, but I want the clean lines of a single block while also having my imperative cake.
The binding as a label is often useful, though you could argue that’s what the function name should be doing. But your point of “you don’t want to use the binding so why bind” is a good one I think.
This confuses me slightly… Please excuse the trivial / useless example, but if this is the case I’m struggling with, how would “put the binding in the body” look?
(let [x 1] x)
then it's a short thing in the body that describes what you're returning, I guess
Here’s a more concrete example and some options, 2 of which are options today and the bottom 2 are examples of what is in my head:
(defn repeat-last-binding [input] (let [a (foo input) c (bar b) d (baz b) output (quux c d)] output)) (defn body-is-last-bound-expression [input] (let [b (foo input) c (bar b) d (baz b)] (quux c d))) (defn labeled-output [input] (let [b (foo input) c (bar b) d (baz b) output (quux c d)])) (defn ignored-binding [input] (let [b (foo input) c (bar b) d (baz b) _ (quux c d)]))
Remember also that the name of the function serves as a name for the last binding (assuming the function is well named and doesn't try to do too much).
And then whether you use version 1 or version 2 depends on whether the last binding
output is obvious from and repeating the name of the function, or not.
In my opinion, using the symbol
_ is a hint that the final binding isn’t adding much clarity or value. Perhaps that is just because this is an example and your real use case uses a more informative name. In that case, I would consider using a comment rather than a binding.
Yes, this is a contrived example, which has other issues as well. eg. the binding symbols are all the same length, enhancing the “tabular” shape of the binding block, when in reality this wouldn’t hold and so the effect would be much less. This is the actual code, from a blog article, which put the question into my head and pointed out the aesthetic problem I’ve been bouncing off of in my own code:
(defn markdown->html [file] (let [markdown (slurp file) ;; make links without markup clickable markdown (str/replace markdown #"http[A-Za-z0-9/:.=#?_-]+([\s])" (fn [[match ws]] (format "[%s](%s)%s" (str/trim match) (str/trim match) ws))) ;; allow links with markup over multiple lines markdown (str/replace markdown #"\[[^\]]+\n" (fn [match] (str/replace match "\n" "$RET$"))) html (md/markdown markdown :data :html) html (str/replace html "$RET$" "\n")] html))
The linear nature here is amenable to just using the thread-first macro, so is also not a perfect example, but the thread macros’ “return the last thing” semantics seem to align well with my sense of aesthetics, since all steps are “at the same level”.
(defn markdown->html [file] (-> (slurp file) ;; make links without markup clickable (str/replace #"http[A-Za-z0-9/:.=#?_-]+([\s])" (fn [[match ws]] (format "[%s](%s)%s" (str/trim match) (str/trim match) ws))) ;; allow links with markup over multiple lines (str/replace #"\[[^\]]+\n" (fn [match] (str/replace match "\n" "$RET$"))) (md/markdown :data :html) (str/replace "$RET$" "\n")))
You have no
let in this example, but if I understand correctly that those comments could serve the same purpose as let bindings (for documentation purposes), I'd argue that those comments and implementation could be replaced by a better-named function
(-> (slurp file) (clickable-links) (tag-multiline-links "$RET") (md/markdown :data :html) (join-multiline-links "$RET$"))
(also in this case the function docstrings could serve as a good place for someone to learn more about why the operation exists)
Yes, the linear nature of that computation makes the thread macro an obvious choice. But what about non-linear computation flows, where there are sub-computations which need to be re-used later?
let makes that possible by giving a name to each step and making all previous steps available “down the line”, but the tradeoff is that the final step which would get returned has to be “special” and outside the aesthetic flow of the rest of the computation steps. Perhaps this is just the tradeoff for the flexibility
let bindings allow for, or that I should use some other sort of
dag-computation macro which is just a series of bindings and a terminal computation which is returned?
I find it reassuring that
let has a final return value that is not dependent on the order of bindings :)
BTW, https://github.com/Engelberg/better-cond macro can be used as an optional set of
let bindings with an implicit final return. Or the
<<- macro I mentioned yesterday: https://twitter.com/cgrand/status/1281527501387440128
🙂 The thought occurred to me, but it seems like either someone’s already done it, the standard lib already has it, or it is a sufficiently bad idea that I shouldn’t do so and should instead adjust my thinking.
it really seems like it doesn't add much value, to me, and it would be surprising to find a
let that worked in this way, imo
Yes, the amount of value add is, admittedly, very small, but it struck me as a “mental snag” when moving from clean thread-macro-based functions to
let-based functions that are structured the same way but with computation logic / steps that were not entirely linear.
it's semantically cleaner to not return the final let binding, imo, even if things align visually. they're expressed differently and that indicates to me that they are doing different things
Let's say I evaluate the following in my editor, via cider-nrepl (and vim-fireplace). What happens to the
prns? How do I capture them? :thinking_face:
(future (loop [i 0] (Thread/sleep 1000) (when (< i 10) (prn "yo") (recur (inc i)))))
it is kind of complicated, but usually I would expect them to go to the same place the repl prompt is printed
prn prints to
*out* which is by default stdout, nrepl will dynamically bind
*out* to something that prints at the repl, and future will copy any dynamic bindings on the thread where it is created to the thread where it runs
if, for example, instead of using future you use something else to launch another thread, and the dynamic bindings are not copied, then it will print to the root/default binding of
*out* which is the same as java's System/out
the output is going to come back asynchronously, and I haven't used vim fireplace or whatever, but my understanding is, at least at one time, that kind of asynchronous output was tricky to handle in vim
Maybe the thing to do is force it to where the repl prompt is printed, then. I'll give that a go...