This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-05
Channels
- # announcements (7)
- # beginners (107)
- # boot (5)
- # calva (2)
- # cider (18)
- # clj-kondo (48)
- # cljs-dev (16)
- # cljsrn (2)
- # clojure (208)
- # clojure-berlin (1)
- # clojure-dev (25)
- # clojure-europe (14)
- # clojure-italy (10)
- # clojure-nl (10)
- # clojure-sg (1)
- # clojure-spec (52)
- # clojure-uk (13)
- # clojurescript (53)
- # cursive (7)
- # data-science (7)
- # datomic (4)
- # duct (1)
- # events (10)
- # fulcro (1)
- # graphql (5)
- # jobs (2)
- # kaocha (13)
- # leiningen (6)
- # off-topic (17)
- # pathom (4)
- # quil (6)
- # re-frame (52)
- # reagent (12)
- # reitit (3)
- # shadow-cljs (97)
- # spacemacs (10)
- # sql (39)
- # tools-deps (18)
- # uncomplicate (1)
- # xtdb (1)
I want to make a function that's invoked like this:
(build {:builder CfnSubnetGroupProps/builder
:cache-subnet-group-name "sup"
:description "sup"
:subnet-ids ["sup"]})
where it ends up doing this:
(-> (CfnSubnetGroupProps/builder)
(.cacheSubnetGroupName "sup")
(.description "sup")
(.subnetIds ["sup"])
(.build))
is a macro the right way to go here?I don't really want to pass the builder object in the map though.
I guess I really want to call something like (CfnSubnetGroupProps/builder {,,,})
except that builder is a 3rd party lib
Looks like a pure function to me that converts a data structure to a series of method calls.
Are you looking for this: https://clojuredocs.org/clojure.core/doto
I thought about (doto
, but didn't know what benefit that provides over the threading implementation
Heya, I am having a bit of trouble with making a list of symbols with selective evaluation. So for example, given that thing
is :Thing
, I want to make a list that looks like (my-symbol (my-other-symbol (my-symbol :Thing)))
. The following works, but feels overly verbose, is there an easier way?
(let [thing :Thing]
(list 'my-symbol (list 'my-other-symbol (list 'my-symbol thing))))
=> (my-symbol (my-other-symbol (my-symbol :Thing)))
I tried this:
(let [thing :Thing]
'(my-symbol (my-other-symbol (my-symbol ~thing))))
=> (my-symbol (my-other-symbol (my-symbol (clojure.core/unquote thing))))
But that appears to not be the same with that ‘unquote’ in the last pos.right, but I don’t want to fqn those symbols (because they don’t exist as def/defns). So this works:
(let [thing :Thing]
`(~'my-symbol (~'my-other-symbol (~'my-symbol ~thing))))
=> (my-symbol (my-other-symbol (my-symbol :Thing)))
Hmm, that helps when you need fresh names right?
yeah, so that local symbols in a macro won't accidentally shadow outer bindings ('hygeine')
right, in this case I just need the ‘exact’ symbol. I don’t think it gets evaluated. Thanks for the help!
@lennart.buit A bit ugly but it also does the job:
(read-string (let [thing :Thing] (format "(my-symbol (my-other-symbol (my-symbol %s)))" thing)))
(my-symbol (my-other-symbol (my-symbol :Thing)))
There's a thread about this problem here: https://clojureverse.org/t/a-macro-between-quote-and-syntax-quote/4466/10haha great, I was looking for the least ugly solution :’)
that magic quote thing is cool tho
personally I would go for ~'
in that case, but that may also be a sign that you're doing it wrong
yeah, I had that feeling as well, of ‘trying to do it wrong’
But you might also look at the largely unused clojure.template which is in core
oh thats used by clojure.test right?
I think I remember it from the internals of are
added this: https://clojureverse.org/t/a-macro-between-quote-and-syntax-quote/4466/16
right, I was just going to add this for posterity:
(let [thing :Thing]
(apply-template '[x] '(my-symbol (my-other-symbol (my-symbol x))) [thing]))
=> (my-symbol (my-other-symbol (my-symbol :Thing)))
uh almost
user=> (t/apply-template '[x] '(my-symbol (my-other-symbol (my-symbol x))) [:Thing])
(my-symbol (my-other-symbol (my-symbol :Thing)))
yeah, I was editing my own words by the power of the internet
thanks for the insights, learned a thing or two today 🙂!
@lennart.buit It seems to be powered by postwalk-replace:
user=> (clojure.walk/postwalk-replace '{_x 10} '(let [x _x] (inc x)))
(let [x 10] (inc x))
and that it turn is just (postwalk (fn [x] (if (contains? smap x) (smap x) x)) form))
I'm in awe of the simplicity of Clojure
yeah was just about to say, did you mean simple
mister-edit-his-words-just-like-I-do
I'm the kind of person who first sends an e-mail and then reads it for corrections... so Slack is better for me than IRC 😉
I think that I edit about 80% of the messages I send
and I get uneasy when I cannot edit my messages, like email or WhatsApp
most annoyingly: Wording yourself badly on GitHub, because you can edit things on GH, but not in the emails that are also sent
I’ll stop with the off-topic
words of a serial-editor
hey, this may be something i overlooked or something really stupid i overlooked, but i’m having a problem removing a key from nested maps. could someone give it a look and explain to me why it doesn’t work the way i think it should?
(defn removex [map]
(let [newmap (dissoc map :x)
children (:children newmap)]
(if (some? children)
(assoc newmap :children (map removex children))
newmap)))
so, say i have
{:a 1 :x 2 :children [{:b 3 :x 4}]}
i’d expect this to remove the :x entry from the toplevel map and overwrite the :children entry with assoc, doing the same thing to every childUsing map
as a name in clojure is dangerous - you shadow the map
function. Use m
Because this line (map removex children)
is being called with your map, not clojure.core/map
and maps are ifns too so no error
no worries - I’ve done it enough times myself 😄
usually with name
there are probably some better more generic ways to do this too
like if your goal is to remove all the :x's, you can (defn removex [m] (clojure.walk/postwalk #(if (and (map? %) (contains? % :x)) (dissoc % :x) %) m))
postwalk will walk the data (bottom-up) and replace each node with the result of the function
so if you encounter something is a map and has x, remove it. otherwise no change
the condition and what you do when it's encountered are completely up to the function you write, so this is a very generic technique that is applicable in a wide range of scenarios
my first try was looking at specter, but since this was a quick and dirty solution i needed i didin’t get any further than “specter is too complicated for what i need right now”, and neither did i look for purposeful solution in the standard libraries
you can also do it with specter
postwalk is unreasonably useful though :) once you think in that way, you see it everywhere
I see there’s more than one walk. what’s the difference between walk, postwalk and prewalk?
walk is the generic tool. postwalk is bottom up, prewalk is top down. you almost always want postwalk
postwalk-replace is useful in specific circumstances
oh i see. my CS education is lacking: names come from pre-order / post-order traversal i guess
those are probably more precise words than bottom-up and top-down :)
when I call swap!
and pass a function that uses remove
, the lazy seq is fully realized, right? i don't have to worry about wrapping it in a doall
or something?
it's not realized, but any further modification would need to realize it...
if you are doing something side-effecting or resource-dependent in the remove call, you do need to call doall
generally lazy things and side effects / contextual resources are a bad fit
this is my current call: (swap! state assoc :events #(remove (fn [event] (same-card? card (:card event))) (:events @state)))
there aren't any side effects except for the swap!
but i'm worried that outdated data might end up in the :events
entry
that puts a lambda under a key
remove doesn't even get called
oh damn, i was thinking of update
when i wrote that
even with update, the value under the key would be passed in, you wouldn't deref inside
removing the anonymous function, should i wrap the remove
call in a doall
?
yes, if it needs to be coherent
okay, good to know
thanks, and sorry for the confusion
something like (swap! state update :events #(doall (remove f %)))
where f is the same as your original
second guessing myself now - doall shouldn't actually be neccessary
doall isn't strictly required, but if you are doing a lot of removes between actual reads of :events which would force the seq, a doall might be a good idea to avoid blowing the stack
yeah, lots of frequent reads, frequent updates/changes
@papachan is there a feature you need that isn't offered by clojure.java.shell/sh?
I tried raynes/conch but found it easier to use ProcessBuilder / Process directly (they come with the jvm)
@papachan See https://clojure.org/community/contrib_history for where everything from contrib went.
In particular "clojure.contrib.shell and clojure.contrib.shell-out migrated to clojure.java.shell".
oh lol it's literally the same code
That all happened as part of the Clojure 1.2 -> 1.3 cycle ("many years ago").
@noisesmith @seancorfield got it! thanks!