This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-21
Channels
- # announcements (4)
- # architecture (161)
- # autochrome-github (7)
- # babashka (61)
- # beginners (42)
- # calva (24)
- # cider (22)
- # clj-kondo (28)
- # cljs-dev (8)
- # clojure (88)
- # clojure-art (2)
- # clojure-dev (7)
- # clojure-europe (43)
- # clojure-germany (2)
- # clojure-nl (2)
- # clojure-uk (4)
- # clojurescript (32)
- # core-async (41)
- # cursive (32)
- # datahike (6)
- # datomic (9)
- # emacs (22)
- # events (2)
- # fulcro (10)
- # graphql (1)
- # nextjournal (16)
- # off-topic (9)
- # overtone (1)
- # pathom (16)
- # polylith (5)
- # quil (7)
- # rdf (1)
- # re-frame (7)
- # reagent (22)
- # releases (2)
- # remote-jobs (1)
- # reveal (12)
- # sci (1)
- # shadow-cljs (12)
- # specter (20)
- # sql (6)
- # tools-deps (21)
- # vim (26)
- # xtdb (10)
Is there a facility for anonymous macros?
In order to expand macros the compiler needs to know at analysis time which symbols name macros, so any kind of higher order kinds of usage, which I dunno what else an anonymous macro would be for, doesn't work
In Count Zero (a book) a character refers to another as a "hired man" (maybe just once?)
@acgollapalli tools.macro does have local macro defs: https://github.com/clojure/tools.macro#example-usages
thanks!
@michael127 have you tried to upgrade amazonica to use the 1.12.* version of aws-java-sdk ? I've found that to use some new features of Timestream I had to upgrade it, and at least for the Timestream it works but of course I am a bit hesitant to make the PR since probably something will break up because there are so many services that Amazonica supports
This article says it's pretty safe to upgrade: https://aws.amazon.com/blogs/developer/aws-sdk-for-java-version-1-12/
I once saw some codeāI think it was by a guy who used to work for Cognitectāthat handled memoization in this way: rather than defāing a new var like (def new-f (memo f))
, the existing var was redefāed as a memoized version of itself. I canāt remember exactly how exactly it was done, so Iām asking here how it might have been handled? It was a simple one-liner.
as a side note, I have a personal rule to always write a comment describing why this particular memoized case will not have unbounded memory growth... just to be careful with it
@UK0810AQ2 Thanks.
@U11SJ6Q0K The problem with doing def
and returning a function is that it breaks statical analysis, e.g. in Cursive.
@U11SJ6Q0K And I do have a note, although that note is about using core.memoize instead, precisely to limit memory use. It is not relevant for now š
Which is useful for recursion. The classic case being fibonacci:
(def fib (memoize (fn [n] (if (< n 2) 1 (+ (fib (dec n)) (fib (- n 2)))))))
Alsoā¦ I almost never use memoize
in production code due to memory use. Iām all about core.cache
@U051N6TTC Also breaks static analysis. The alter-var-root
trick is the best if you want Cursive to know that itās dealing with a function. Just a shame it doesnāt work in CLJS.
Sorry, I have no idea what static analysis does here, nor what it provides, as Iāve never used Cursive. I was responding to the one-liner part
Have you successfully show line number with logback? With this setup
<pattern>%date{ISO8601} [%thread] %-5level %logger{36} line:%line - %msg %n</pattern>
I see inaccurate line number showing upWhen you also add %file
, you will likely see that all messages seem to origin from the same clojure file (depending on how you log to Logback).
I think Clojure does not support exposing line numbers to the logging framework.
How are you using Logback? Through clojure.tools.logging
?
Then you will not receive meaningful filenames or line numbers in your log.
@U031CHTGX1T How do you bypass this? With (:line (meta &form))
in a macro?
Not sure how this is transported, sorry
How do you handle conditional vectors & hash-maps?
(->> [:a
(when true :b)]
(filter identity))
(->> [(when true {:b 2})]
(into {:a 1}))
Any better ways come to mind?(cond-> [:a] true (conj :b))
(cond-> {:a 1} true (assoc :b 2))
what does "conditional vectors & hash-maps" mean?
Note that, unlike cond branching, cond-> threading does
not short circuit after the first true test expression.
https://clojuredocs.org/clojure.core/cond-%3Ethen, as already mentioned here, there is a spectrum of conditional functions in clojure. like cond->
I've had a colleague argue for using splice-unquoting:
`[1 2 ~@(when foo [3])]
I wasn't a fan although it's arguably more declarative š(defn bar [foo]
`[1 2 ~@(when foo [3])])
(defn bar' [foo]
(cond-> [1 2]
foo (conj 3)))
(time
(dotimes [_ 10000]
(bar true)))
;; => 23.4ms
(time
(dotimes [_ 10000]
(bar' true)))
;; => 1.5ms
I think the merge\concat approach is my favorite so far, I like the way it makes the intention really clear. Also like the splice approach, that's pretty concise!
cond-> works too, didn't consider that one but feels like too much given each pair would have a consistent operation so specifying it each time here is not ideal to me
You can easily write your own macro around cond->
, something like cond->conj
or cond->assoc
- it would be the most terse and, given a proper name, the most clear.
(concat []
(if meeting-url
[(b/text {:href meeting-url} "ā")]
[(b/text {} ":no_mobile_phones:")])
[(b/text "\t")
(b/text
(str (date/time time-zone start)
" - "
(date/time time-zone end)
" "
summary))])
Ended up switching from a when
to an if
so it seems like concat is well suited for this. The cond approach would require a separate meeting-url
and (not meeting-url)
clausesBut in this case, your whole block could be replaced with:
[(if meeting-url
(b/text {:href meeting-url} "ā")
(b/text {} ":no_mobile_phones:"))
(b/text "\t")
(b/text
(str (date/time time-zone start)
" - "
(date/time time-zone end)
" "
summary))]
I'm not talking about formatting here but rather about the lack of need for concat
and that []
, along with []
within if
.
You can make do with a single vector in this particular case.
I'm just saying I'm not 100% on what I want this program to do so the flexibility is useful for now, if it doesn't change will probably optimize it
tangential note, into
if you will :) https://stuartsierra.com/2015/04/26/clojure-donts-concat
I also take it as "distinguish between seq and coll fns" often people will use a seq fn whereas a coll one performs better and has no big difference
(Honestly, I use merge
nil-punning way more than concat
anyways. Itās fairly uncommon to have conditional concating.)
(conj {} [:a 1]) ;;=> {:a 1} could help
is there a json library that will pretty-print maps with sorted keys?
A slightly different question, but the answers might be relevant: https://clojurians.slack.com/archives/C03S1KBA2/p1644497018889889
Alternatively, you can just walk
the resulting data structure in any way you want and replace all map with sorted ones, and then pprint
it - all via built-in means.
hm yeah, i'll have to check that out
walk is a little more annoying than i'd hoped would exist, but i'll figure something out
walk
will be much less annoying than anything else that doesn't provide a one-line argument like :map-factory sorted-map
. :)
hah right, which is what i was hoping for
(require '[clojure.walk :as walk])
(defn deep-order-maps [v]
(walk/postwalk (fn [x]
(cond->> x
(map? x) (into (sorted-map))))
v))
found the solution for my purposes: (into (sorted-map) existing-map)
will decode into a sorted json object using cheshire/generate-string
oh excellent, that's even better cuz it's recursive
Started off doing a bit of math in an interactive repl I can embed into a doc, turned into "let's overengineer this for fun!" https://replit.com/@eccentric-j/Convertor#main.clj. Working on v2 now to support remainders for more sophisticated calculations
Officially over-engineered https://replit.com/@eccentric-j/conversion-v2#main.clj now but it was fun and learned a bit more about the differenced between symbols and vars. If anyone also finds it kind of fun to solve these trivial problems I'd be interested to see what people come up with!
Hi folks. Does anyone know any lib or function that āflattensā maps in this way? from
{:foo {:bar {:baz 1}}
:xum 5}
to something like
[:foo :bar :baz 1]
[:xum 5]
Humm. Why does it have two args? One should suffice. Just to clarify, itās supposed to work like this:
(f {:a {:b 2}})
;; => [[:a :b 2]]e
The first arg is for the recursive call. You can add another arity that would call the 2-arity with []
as the first argument.
There's also a bug in there where it loses k
in the false
branch.
Here's a fixed and formatted version:
(defn f
([m]
(f [] m))
([p m]
(for [[k v] m
i (if (map? v)
(f (conj p k) v)
[(conj p k v)])]
i)))