Fork me on GitHub
#clojurescript
<
2021-10-21
>
Simon09:10:04

How do i pass on every non destructured parameter, such that e.g. :color and others is also included in the resulting map?

(defn testfn [{:keys [icon size]
                 :or {size 24}} & rest]
    (merge {:icon icon :size size} rest))

  (testfn {:icon "icon" :size "big" :color "yellow"})
  

Simon09:10:14

i could pass on everything like this, but then i would not be able to set default values for some of them:

(defn testfn [everything]
    everything)

  (testfn {:icon "icon" :size "big" :color "yellow"})

Simon09:10:56

This solves the problem, but i don't know if it is idiomatic:

(defn testfn [everything]
    (let [ {:keys [size]
            :or {size 24}} everything]
      (merge everything {:size size})))

  (testfn {:icon "icon" :size "big" :color "yellow"})

p-himik10:10:47

That's what I do when I need to distinguish between a value being set to nil and not being set at all:

(let [params (cond-> params
               (not (contains? params :size))
               (assoc :size 24))]
  (do-something params))
And when such distinction is not needed (would need to be altered a bit if you need false as well):
(let [params (update params :size #(or % 24))]
  (do-something params))

maverick12:10:39

I have an atom with values as (def values (atom {:data [{:a "test"} {:a "new"}]})) I want to remove map from :data where :a = "test"

vanelsas12:10:35

you can use filter to remove any value. Or remove.

p-himik12:10:44

Lookup update and filterv. And of course swap!.

p-himik12:10:31

Also, such questions are more suitable for #beginners

maverick12:10:33

I tried (reset! values assoc-in [:data] (remove #(= (:a %) "test") (:a @values)))

p-himik12:10:51

Please read the docstring for reset!. In REPL, it's as easy as (doc reset!). And then do the same for the functions I mentioned above.

Simon15:10:11

Why don't we have a macro that makes it more convenient to do async tests? instead of this:

(deftest test-async
  (async done
    (http/get ""
      (fn [res]
        (is (= res :awesome))
        (done)))))

borkdude15:10:35

@U024A5W9WBG Because this gives you all you need to write your own situational macros :)

borkdude15:10:54

I have one such macro here: https://github.com/borkdude/nbb/blob/015c5618c0b0cc173a0f5e1fe3335529f2d04d59/test/nbb/test_macros.clj#L3 But this is specific to my promise based use cases.

🙌 1
Simon16:10:27

What do you use instead of thrown? from clojure in cljs.test ? I am running this test:

(deftest test-filter-cities-by-flight-time
  (let [cities [{:name "portugal"
                 :flight-time 10}
                {:name "portugal15"
                 :flight-time 15}
                {:name "portugal20"
                 :flight-time 20}]]
    ...
    (testing "max is less than min"
      (-> (filter-cities-by-flight-time cities 10 0)
          (= js/Error) ; <<<<
          (is)))))

Simon16:10:48

When using clojure.spec

Simon16:10:09

(ns app.components.city-list.subs
  (:require [re-frame.core :refer [reg-sub]]
            [clojure.spec.alpha :as s]
            [clojure.spec.test.alpha :as stest]))

(defn filter-cities-by-flight-time [cities min max]
  (filter (fn [city]
            (<= min (:flight-time city) max))
          cities))

(filter-cities-by-flight-time [{:one 1} {:two 2}] 0 10)

(s/fdef filter-cities-by-flight-time
  :args (s/and (s/cat :cities coll? :min int? :max int?)
               #(<= (:min %) (:max %))))

(stest/instrument 'app.components.city-list.subs/filter-cities-by-flight-time)

Simon16:10:03

and the returned value from the function call given parameters that doesn't follow the spec is this:

#error {:message "Call to #'app.components.city-list.subs/filter-cities-by-flight-time did not conform to spec.", :data {:cljs.spec.alpha/problems [{:path [], :pred (cljs.core/fn [%] (cljs.core/<= (:min %) (:max %))), :val {:cities [{:name "portugal", :flight-time 10} {:name "portugal15", :flight-time 15}....

Simon16:10:16

There might also be a better way of using clojure.spec with cljs.test if at all possible?

genRaiy18:10:32

I would like to use the specs in cljs.core.specs.alpha to conform / unform forms but it seems that they are only available via macros (says @thheller and he seems, as usual, to be right)

genRaiy18:10:09

is there any way around that?

genRaiy18:10:41

[ I will bit the bullet but just wanted to double check that it was the only option ]

dnolen19:10:51

specs are all runtime stuff, the macros primarily provide sugar - not sure what you want to do - but it should be possible

borkdude19:10:17

the issue is that the core specs .cljc namespace is loaded only via :require-macros in a same-named .cljs namespace which makes them not defined in .cljs at runtime, but only when loading macros from the .cljc file

genRaiy20:10:55

what he said

genRaiy20:10:55

in the end I just copied the specs into my own ns and removed the fdef stuff and it all works ... easiest hack available

genRaiy20:10:28

@dnolen if the specs were in a CLJS namespace (which is what I ended up doing) they would all be available directly to conform / unform in CLJS. At the moment that direct route is not possible. Unless you have a trick?

genRaiy20:10:54

there is also a https://clojure.atlassian.net/browse/CLJ-2021 in unform (that's a Clojure bug) but still, quite the time sink cos https://blog.klipse.tech/clojure/2019/03/08/spec-custom-defn.html also had a bug (now fixed by the lovely @viebel)

genRaiy20:10:56

this is the cost of trying to believe "code is data and data is code" 🙂

dnolen20:10:47

I’ll have to look at it - but the specs are in a private atom - you could just get them

dnolen20:10:04

They have to exist at runtime somewhere

dnolen20:10:11

So I think copy pasta not necessary

genRaiy20:10:37

💯 would definitely be good to not do that !

genRaiy20:10:49

if you get the time to let me know where to look, that would be great

dnolen20:10:27

Just look for the atom that stores the specs

dnolen20:10:43

AFK so can’t tell you right now

genRaiy20:10:56

(defonce ^:private _speced_vars (atom #{}))

(defn speced-vars []
  @_speced_vars)

genRaiy20:10:04

^^^ that one?

dnolen20:10:53

That for instrumentation there has to be another thing for storing spec names to specs

genRaiy20:10:17

like the (defonce registry-ref (atom {}))

genRaiy20:10:40

ok, anyway ... it's late for me

genRaiy20:10:27

I'm gonna bail and if you have a moment to look @dnolen it would be great, otherwise I'll follow up tomorrow. Thanks for the tip in any case!

Alex Miller (Clojure team)20:10:07

that sounds like it to me based on the clj spec

borkdude21:10:43

you can get the spec using s/get-spec but in the CLJS runtime this returns nil because those specs aren't defined in the runtime, only at JVM compilation time during macro loading I know this is in general not true, but for this specific example it works like that because of the .cljs + .cljc combination where the .cljs file only does (:require-macros ...)

borkdude21:10:21

if you copy paste them in the CLJS REPL, then s/get-spec does return the spec

dnolen22:10:16

@borkdude are you talking about the syntactical specs? I probably missed some earlier detail