Fork me on GitHub
#clojure
<
2022-10-08
>
lilactown14:10:06

if you were using a library whose primary utility was to extend some protocols to an existing type, would you prefer that it did that automatically on require or only after calling a function like install! or something?

borkdude14:10:46

@U4YGF4NGM on require would be fine with me (I've done the same with protocols and specs)

1
1
vemv15:10:55

Why not both? A .core ns with the install function (which I would name start and plug it into Component/etc client-side) and a .auto ns that calls (start) at compile-time So consumers can choose their prefered approach

vemv15:10:29

From my side I don't like to be one tooling-config mistake away from a prod issue, has happened to me, never again

ahungry17:10:57

Hey all - what's the deps.edn approach to simulate the lein option for initial ns? it has something such as this:

{:profiles 
  :dev {:repl-options {:init-ns app.core}}
The scenario is, when I load up with my -A:dev alias in deps.edn, I would like to end up in my app's main file (or at the very least, have it pre-loaded into my top level "user" ns, or automagically load a dev/user.clj file which can do that busy work)

flowthing18:10:29

{:aliases {:dev {:extra-paths ["dev"]}}}

flowthing18:10:00

tools.deps doesn’t have a direct :init-ns equivalent.

flowthing18:10:36

(Note that having user.clj load your app’s entry point namespace might impact your REPL startup time pretty significantly, though: https://blog.flowthing.me/clojure-repl-start/)

thanks3 1
seancorfield18:10:20

@U96DD8U80 Would this satisfy you?

seanc@Sean-win-11-laptop:~/clojure$ cat deps.edn
{:aliases
 {:dev {:extra-paths ["dev"]
        :main-opts ["-e" "(do (require 'startup) (in-ns 'startup))" "-r"]}}}
seanc@Sean-win-11-laptop:~/clojure$ cat dev/startup.clj
(ns startup)
(println "Starting up dev...")
seanc@Sean-win-11-laptop:~/clojure$ clj -M:dev
Starting up dev...
#object[clojure.lang.Namespace 0x1827a871 "startup"]
startup=>

👍 1
thanks3 1
seancorfield18:10:14

Obvs the :dev alias could require any ns and jump into it.

pez21:10:49

I want to update a map at some given paths. Created this function:

(defn update-in-paths
  "Returns `m` where all `paths` are updated with `(f value-at-path)`"
  [m paths f]
  (reduce (fn [acc path]
            (update-in acc path f))
          m
          paths))
Which is fine so far.
(def m {:a 3 :b {:x true :y [:z "z"]} :c 4})
  (-> m
      (update-in-paths [[:b :y] [:c]] str)) => {:a 3, :b {:x true, :y "[:z \"z\"]"}, :c "4"}
Now the problem is that I want to also be able to specify that all entries in some vector at the path should be updated. Something like
(def m {:a 3 :b {:x true :y [:z "z"]} :c 4})
  (-> m
      (update-in-paths [[:b :y :*] [:c]] str)) => {:a 3, :b {:x true, :y [\":z\" \"z\"]"}, :c "4"}
My brain seems to implode when trying to figure out how I should do this. And I also suspect that there might be a library that could help. I need this for Calva, so helping me here is helping a poor open source dev with a tired brain. 😃

pez21:10:06

Also. I'm using ClojureScript. For any library suggestions.

p-himik21:10:20

Ah, and the library by that link already mentions Specter.

pppaul21:10:11

specter does a lot more, but also is a DSL that requires a bit of learning

pez21:10:45

supdate looks pretty spot on. I think I like it's syntax for updating all values in a vector better than the idea I had for it.

pppaul21:10:13

it's syntax is similar to pattern matching, you may be interested in core.match https://github.com/clojure/core.match

pez21:10:26

It works like charm!

Joshua Suskalo22:10:22

I still like Specter's solution here and I think it's worth learning for performance as well as power.

(multi-transform (multi-path [:b :y ALL]
                             [:c])
                 str
                 m)

1
Lone Ranger01:10:25

I haven’t checked in a few years, is there a more systematic way to learn specter yet besides constantly pestering Nathan with questions?

p-himik07:10:01

I was pretty happy with its guide, examples, and source code.

pez11:10:27

@U02KYBC5WJY Spectre looks pretty rad. I think it could be great material for your audience. Just sayn'. Seems like you could recruit someone to record with in this thread. 😃

👀 1
pez11:10:42

core.match is also pretty mind blowing, btw.

Max13:10:01

Medley has considered adding a fn that lets you use update as a sort of mini-language for nested updates, I think it’s rather elegant https://github.com/weavejester/medley/issues/63#issuecomment-1112233476

pez15:10:16

It probably shouldn't surprise me that we have this abundance of options, but anyway, it amazes me. 😃 This is the example from that medley PR solved with supdate:

(def m {:users [{:id 1 :orders #{{:items [{:price 1} {:price 4} {:price 2}]}}}
                {:id 2 :orders #{}}]}) 
(-> m 
    (supdate {:users [{:orders [{:items [{:price #(str "$" %)}]}]}]})
    (supdate {:users [{:orders set}]}))
=>
{:users [{:id 1 :orders #{{:items [{:price "$1"} {:price "$4"} {:price "$2"}]}}}
         {:id 2 :orders #{}}]}
A bit boring with the restoring of the set type, but anyway.

pppaul17:10:58

the syntax looks a bit like dataomic pull/ednQL. i think you probably identified a bug, though. i don't like it when high level DSLs change my types, and clojure has an ok way of preserving types via (->> my-obj transform-fn (into (empty my-obj)) clojure.walk is a good example of transformation code that doesn't change types. seems like a good bug to report

pppaul17:10:53

https://github.com/turtlegrammar/faconne this is a really cool idea i came across when searching around for declarative data transformations. this lib does have some common edge cases where it breaks (seems to fail on nil cases). i think the self documenting syntax is pretty elegant.

zeitstein08:10:50

Thanks all for bringing supdate to my attention! I think it's a more comfortable alternative to threading macros (e.g. in event handlers for shadow-grove or re-frame). I do need assoc though, so I'll probably just fork the supdate* fn and keep it simple for now.

zeitstein08:10:52

Here's what I ended up with:

(dtf
    {:a 1
     :b {:c 3 :d #{4}}
     :e :replace-with-num
     :f :replace-with-vec
     :g :replace-with-set
     :h :replace-with-map}
    {:a dissoc
     :b {:c inc :d [inc]}
     :e 6
     :f (constantly [3 4])
     :g #{1 2}
     :h (constantly {"a" "b"})
     :new {:foo :bar}})
  := {:b {:c 4, :d #{5}}
      :e 6
      :f [3 4]
      :g #{1 2}
      :h {"a" "b"}
      :new {:foo :bar}}