This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-01
Channels
- # announcements (10)
- # asami (2)
- # babashka (10)
- # beginners (55)
- # biff (37)
- # calva (9)
- # cherry (1)
- # clj-kondo (11)
- # clojure (221)
- # clojure-bay-area (12)
- # clojure-europe (77)
- # clojure-hungary (3)
- # clojure-nl (5)
- # clojure-norway (12)
- # clojurescript (11)
- # cursive (1)
- # data-science (11)
- # emacs (27)
- # figwheel (3)
- # fulcro (11)
- # graphql (5)
- # helix (7)
- # honeysql (3)
- # humbleui (9)
- # interceptors (2)
- # introduce-yourself (2)
- # kaocha (12)
- # lsp (27)
- # malli (6)
- # nbb (70)
- # off-topic (6)
- # re-frame (6)
- # react (3)
- # reitit (9)
- # releases (2)
- # scittle (29)
- # shadow-cljs (26)
- # sql (13)
- # tools-deps (61)
Is it fine to do value transformations using a malli schema then validation using the same schema?
yes, it’s a common pattern to what Plumatic calls Coercion. See https://www.metosin.fi/blog/high-performance-schemas-in-clojurescript-with-malli-1-2/#transformation for sample code & perf
I find myself doing (walk/postwalk walker-2 (walk/prewalk walker-1 user-data))
to transform some xml data into something useable. Is this a smell?
(= (symbol 'foo) (clojure.edn/read-string "'foo"))
;;=> false
I just realized I don't really get how symbols work 😕
What do I need to do to make this work?
Context in 🧵I have data that looks like this:
"[{:tasks ['path.to.ns.a/foo 'path.to.ns.a/bar 'path.to.ns.a/baz] :other-key :other-value, :etc :etc},
{:tasks ['path.to.ns.a/foo 'path.to.ns.a/bar 'path.to.ns.b/baz] :other-key :other-value, :etc :etc}]"
and my goal is to remove the items that have .ns.b/baz
in the tasks. I can't get the comparison to work though
This is the first thing I tried:
(let [data "[{:tasks ['path.to.ns.a/foo 'path.to.ns.a/bar 'path.to.ns.a/baz] :other-key :other-value, :etc :etc}, {:tasks ['path.to.ns.a/foo 'path.to.ns.a/bar 'path.to.ns.b/baz] :other-key :other-value, :etc :etc}]"]
(->> (clojure.edn/read-string data)
#_(map :tasks)
(filter #(some #{'path.to.ns.b/baz} (:tasks %)))))
... along with variations that convert the symbols to other types, e.g. string
I'm pretty sure I'm missing something but I'm not seeing it.> edn doesn't support quoting ' -- it is accidental that that doesn't error Oh, I didn't know that, thanks so much for the explanation 🙂. Both result in a symbol, so I assumed it doesn't make a difference (I never had to compare them before).
Is there a way to destructure a sequence directly into a map e.g.:
[1 2 3] => {:value1 1 :value2 2 :value3 3}
that seems to be the opposite of destructuring
but (zipmap [:value1 :value2 :value3] [1 2 3])
I would like to be able to specify they key names during the destructuring (for a known number and set of values)
Ahh ok, not familiar with zipmap, will take a peek at that
So while I guess “destructuring” is maybe not the right term, I guess it’s destructure, then “restructure” lol.
destructuring is about binding locals to parts of a value. as soon as you introduce new things (the keys here), you are beyond what destructuring does
but that's ok, we've got lots of library functions to do all that :)
Really what I want is an efficient way to have
{:a [thing] :b [thing] :c [thing]}
and populate that directly with an array where the first item in the map gets the first value in the array and so forth.But maybe zipmap can do this
well, zipmap
constructs a map that way
perfect. Thanks sir for the pointer!
if you haven't found https://clojure.org/api/cheatsheet, you might find it helpful
I have thanks - I just somehow missed the zipmap item in there. Still just a few weeks into clojure and a lot to take in 🙂 Having a blast learning though.
I have thanks - I just somehow missed the zipmap item in there. Still just a few weeks into clojure and a lot to take in 🙂 Having a blast learning though.
the built-in constructors are not variadic but seems like you could easily make one around it (even generically if you plumb the defrecord data), depending on what you actually want
the whole idea with records is that there are slots are you are filling them, so variadic constructors doesn't really match great with that. if you want partial / arbitrary order, the map->MyRecord
constructor seems like an easy path
Wanting a key that is "optional" but defined as a field, ideally being able to define some default, but still useful if it could just default to nil
.
records support arbitrary "extra" keys
so you automatically have optional, nil values of any possible key
you can not define :c at all
user=> (defrecord Foo [a b])
user.Foo
user=> (def f (->Foo 1 2))
#'user/f
user=> (keys f)
(:a :b)
user=> (get f :c)
nil
user=> (def f' (assoc f :c 3))
#'user/f'
user=> (keys f')
(:a :b :c)
user=> (get f' :c)
3
records are open, just like any other Clojure map
(but optional stuff is slower to access and you may be just as well off with a regular map if you're using extended records a lot - depends if you need the type)
Got it. But I was asking about a variadic constructor, such that I can include / not include a field on construction. I take it you are saying "No, not possible"?
you can make any function you like :)
but you won't get that automatically with defrecord
there are some tricks to macro-ize this kind of thing by utilizing some undocumented basis fields in the generated type as that can tell you what fields exist
Wouldn't know where to start on "undocumented basis fields". (I don't even know what a basis field is. 😛)
user=> (Foo/getBasis)
[a b]
it's just the names of the field symbols you created the defrecord with
so you could for example, write a macro that given a type, could emit a function that called the positional constructor that looked at the count of the basis fields and the variadic args you have, pad them and invoke the positional constructor
Thanks. Sounds like overkill for what I'm working on. But I think I need to make an attempt at that, so I don't lose the context of this discussion.
for a known record type, it's pretty easy to write the function:
user=> (defrecord Foo [a b c])
user.Foo
user=>
(defn v->Foo [& fs]
(let [c (count (Foo/getBasis))]
(apply ->Foo (take c (concat fs (repeat c nil))))))
#'user/v->Foo
user=> (v->Foo 1)
#user.Foo{:a 1, :b nil, :c nil}
user=> (v->Foo 1 2)
#user.Foo{:a 1, :b 2, :c nil}
user=> (v->Foo 1 2 3)
#user.Foo{:a 1, :b 2, :c 3}
user=> (v->Foo 1 2 3 4)
#user.Foo{:a 1, :b 2, :c 3}
macroizing that is harder, but definitely possible