This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-24
Channels
- # announcements (3)
- # babashka (47)
- # beginners (38)
- # biff (21)
- # calva (12)
- # cider (2)
- # clj-kondo (25)
- # cljsrn (4)
- # clojure (14)
- # clojure-berlin (2)
- # clojure-conj (1)
- # clojure-dev (24)
- # clojure-europe (84)
- # clojure-italy (8)
- # clojure-nl (1)
- # clojure-spec (1)
- # clojure-sweden (2)
- # clojure-uk (2)
- # clojurescript (34)
- # clr (3)
- # community-development (1)
- # cursive (12)
- # datalevin (8)
- # datomic (5)
- # defnpodcast (2)
- # dev-tooling (1)
- # etaoin (4)
- # events (3)
- # fulcro (23)
- # graphql (3)
- # honeysql (6)
- # hyperfiddle (45)
- # lsp (37)
- # malli (1)
- # missionary (1)
- # nbb (18)
- # podcasts (1)
- # reagent (8)
- # reitit (1)
- # releases (2)
- # ring-swagger (1)
- # scittle (78)
- # shadow-cljs (96)
- # vim (7)
- # xtdb (3)
Quick instructions on setting up a project for logging with logback and SLF4j (everything all in one place in 82 words (- xml file config :)). https://github.com/ftravers/dotfiles/blob/master/homedir/org-roam/clojure.md#logback--slf4j
what is the best way to create html table with row numbers in clojurescript hiccup? I have found map-indexed function:
(defn table-with-row-numbers [videos]
[:table
[:thead
[:tr
[:th "Row Number"]
[:th "Video Title"]]]
[:tbody
(map-indexed (fn [i video]
[:tr
[:td (inc i)]
[:td (:title video)]])
videos)]])
or maybe don't even start with counters in 'for'' and add row number in CSS?I use for
to create html structure (div rather than table) and pass a hash-map of data with the values used in that structure
the generator functions in the Practical landing page use this approach
If numbering is important it could be added to the data passed into the function and if necessary the data sorted by the number value before used in for.
(not suggesting this is best, as best is relative to what best actually means and possibly the significance of the numbers
https://github.com/practicalli/practicalli.github.io/blob/live/src/practicalli/books.cljs
I have found map-indexed is super useful with React because React wants each item in a list to have a distinct key. Of course keys representative of their item are most likely to help React avoid work if you make certain kinds of updates to the list, but a sequential counter is a convenient second-best. I.e., [:tr {:key (str i)} ...
Hey guys. Is there a rule of thumb for when should I pass a full map versus when should I pass single parameters? For example, I have this kind of state
(def sample-state
{:head [0 0]
:tail [0 2]})
Then I am not sure when should I write my function like this:
(defn f [head tail])
Or like this
(defn f [state])
For more context: I am solving Advent of Code Day 9, where there is head
and tail
moving on a 2D map. I figured out that I should have a state
that represent the two variables, and multiple functions to determine additional information or advance the state
..... ..... .....
.TH.. -> .T.H. -> ..TH.
..... ..... .....
... ... ...
.T. .T. ...
.H. -> ... -> .T.
... .H. .H.
... ... ...
What are the semantics of function f
? Indeed, what is the real name of f
? And what is the real name of sample-state
? I do not think Clojure itself dictates any answer, the API being built decides that.
So if f
expects a list and knows about how you are encoding that, you can pass sample-state.
If f
is ... well, if (defn f [state] ...)
is even an option, it must know about the data structure. So I would pass that rather than pull it apart and create a point of brittleness should the state structure have to change.
my2 🤷
> "It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." This quote is from Alan Perlis' Epigrams on Programming (1982). So I usually peek one function form that meets my current needs best. And if I need another later, I can add one more function.
(defn f [head tail])
(defn f* [{:keys [head tail]}]
(f head tail))
to the point of the question “what is the purpose of the function”, another way to think of it is in term of the architectural layers. a representing pattern being, 3 categories of functions, one that operates on scalar values, the next level up (that may or may not use the previous layer) operating on entities (or rather maps), the final being usually an aggregation point but that operates on sequences. so, the intent of the function, driving the type of parameter list it accepts.
order of parameters is also an important consideration, which can heavily influence the ergonomics of use later when using compositional mechanics like partial
, comp
, ->
, transducers, etc.
rarely going to be perfect on the first pass, but important to pay attention and try to get in a decent shape up front. from experience, in the long term in massive code bases, there can be a lot of pain/confusion until these considerations are addressed.
@U0PUGPSFR @U04V4KLKC @UE4SAM0A0 thanks a lot for your answers. I updated the question for more context, but I think I had my answer: in this case, just pass a map since it is going to be simpler to use with reduce
My only rule of thumb is to define functions that take a hash-map as an argument unless there is on obvious need not too I like to give my values context regarding their purpose as it makes the code easier to work with A hash-map also give a lot of flexibility as to what information can be received and allows the API of the code to grow with less chance of breaking changes or creating similar functions
I’m trying invoke clojure while setting a system property and don’t seem to have quite the right syntax. I’ve tried
clojure -M -m my.main.ns -J 'Dmy.main.props=test/resources/cfg.properties'
clojure -J 'Dmy.main.props=test/resources/cfg.properties' -M -m my.main.ns
and a few other variations thereof but nothing seems to set the propertyclojure -J-Dmy.main.props=test/resources/cfg.properties -M -m my.main.ns
that should work
it’s in clj --help
> clj-opts:
> -Jopt Pass opt through in java_opts, ex: -J-Xmx512m
(i always go back and reference this so letting you know where you can find it)
Someday I will cat
something that I spit and not get [email protected]
but today is not that day. What’s the correct version of my incorrect
(spit "midnight-fails.txt" (doall (for [[scenario message] (apply concat (brief-failure-info failures))]
{:scenario scenario
:message message})))
?have you tried clojure.pprint/pprint
?
usually, if you're writing edn, then you should use some variant of clojure.pprint/pprint
, pr
, or pr-str
.
with the caveat that writing readable edn reliably is tricky and at the very least, want to explicitly set the various bindings that control printing. Here's an example:
(defn write-edn [w obj]
(binding [*print-length* nil
*print-level* nil
*print-dup* false
*print-meta* false
*print-readably* true
;; namespaced maps not part of edn spec
*print-namespace-maps* false
*out* w]
(pr obj)))
I’ve used pprint in the past, I’m just always thrown by some missing understanding around how side effects and lazy sequences interact
I thought that if I chucked a doall
in there, it would make everything evaluate, and only then would the spit occur
> I thought that if I chucked a doall
in there, it would make everything evaluate, and only then would the spit occur
That is what is happening, but calling spit
calls str
on the content. The .toString
method for for
's return value is always [email protected]
regardless of whether it has been realized.
> (str (doall
(for [i (range 3)]
i)))
"[email protected]"
(I don’t mean, as distinct from edn…. I’m just trying to get data to paste to someone who isn’t running a Clojure notebook)
something like:
(require '[ :as io])
(with-open [w (io/writer "my-file.edn")]
(write-edn w my-data))
you can also use spit
with pr-str
I only use spit
as a quick and dirty option. Usually, using the
stuff is a similar amount of code and is easier to tweak to fit the use case.
same goes for slurp
.