Fork me on GitHub
#beginners
<
2021-05-24
>
Jacob Rosenzweig04:05:59

Lol I love how destructuring on the sequential order instead of the names takes care of a suite of problems I regularly see in JS.

solf04:05:33

Clojure does both array and map destructuring, if that’s what you’re referring to:

(defn foo [{:keys [foo]}]
  foo)

(foo {:foo 42})

(defn bar [[_ bar]]
  bar)

(bar [10 40])

😄 2
valerauko06:05:10

is there a way to make leiningen automatically update pom.xml whenever there are changes to the project dependencies?

dharrigan06:05:54

Consider this? this will update your pom.xml and your project.clj too 🙂

valerauko06:05:35

that's in a bit different direction... i'm using lein-ancient currently for that purpose and it's alright

valerauko06:05:53

my issue is that when somebody on the team changes/adds dependencies in project.clj they have to manually do a lein pom afterwards

valerauko06:05:59

which is prone to be forgotten

valerauko06:05:34

thus i'd want to automate updating pom.xml but i have no idea how

dharrigan07:05:03

antq can update the pom directly, by excluding others

dharrigan07:05:05

also, if you were to use antq, for example, then it would update the project.clj and the pom.xml too

dharrigan07:05:40

alternatively, you could have a git commit hook (assuming you are using git) that would invoke the update to the pom (via lein or antq) before committing.

valerauko12:05:26

thanks, i'll give it a try

valerauko12:05:09

but as i said, the issue isn't really about keeping dependencies up to date, it's about keeping pom.xml and project.clj in sync without any manual intervention

dharrigan12:05:47

:thumbsup: 🙂

lassemaatta12:05:43

Perhaps a git hook might help?

valerauko13:05:51

that has occurred to me, but i find git hooks really difficult to share across the team.

valerauko13:05:13

do you know a way that could be overcome? (eg i can't check .git/hooks/pre-push in)

lassemaatta13:05:41

Based on a quick browse through google, I believe git > 2.9 supports defining the location of the hooks -> you can create a directory for them and commit them. I haven’t tried this, but it might be what you’re looking for.

valerauko13:05:11

i think i've seen that too, but i couldn't get a repo-local config of that working

Endre Bakken Stovner13:05:46

How would you write the Python example at the bottom idiomatically in Clojure? I guess you could use

(apply merge-with <some-custom-func> (into {} [[1, 2], [1, 4], [2, 5], [2, 4]])) 
But can I get away with using a built-in function?
from collections import defaultdict
l = [[1, 2], [1, 4], [2, 5], [2, 4]]
d = defaultdict(list)
for (parent, child) in l:
    d[parent].append(child)
print(dict(d.items()))
# {1: [2, 4], 2: [5, 4]}

ghadi13:05:28

(doc group-by)

Endre Bakken Stovner13:05:17

Derp. It is a function I know inside out 😳 So the solution is group-by then merge-with.

Endre Bakken Stovner13:05:04

I am sure someone can do it moar purdy:

(def l [{:a 1 :b 2} {:a 1 :b 3} {:a 4 :b 5}])
(def g (group-by :a l))
(zipmap (keys g) (for [l (vals g)] (flatten (for [{:keys [a b]} l] [b]))))
;; {1 (2 3), 4 (5)}

NoahTheDuke13:05:07

user=> (def l [[1, 2], [1, 4], [2, 5], [2, 4]])
user=> (reduce (fn [m [k vs]] (assoc m k (mapcat next vs))) {} (group-by first l))
{1 (2 4), 2 (5 4)}

🙏 1
NoahTheDuke13:05:30

or (reduce (fn [m [k vs]] (update m k conj vs)) {} l), don’t even need the group-by

🙏 1
Endre Bakken Stovner15:05:32

I love this answer. The fact that I can conj to nil Haskell-style and get a list is going to make much of my code cleaner.

😊 1
Joni Hiltunen15:05:41

Sorry if this is the wrong channel... Garden/Spade specific. I'm trying to get started with the re-frame template and I included garden+spade but I can't figure out how I would set a hoverattribute for my links 😄 any tips? https://gist.github.com/Sose/79e79d9b37efdbfe50cb202d94c3e3c7 or if anyone knows any example projects online that use garden+spade so I could dig around their code

Joni Hiltunen15:05:47

okay, I figured it out with help from https://libraries.io/clojars/hendekagon%2Fgarden ... it's [:&:hover {:color :blue}]

Rob Haisfield16:05:29

As a beginner, Instarepl looks really helpful and I would love it if there were a new maintainer https://github.com/LightTable/ClojureInstarepl

seancorfield17:05:29

I think you can get this functionality in a few other editors — but automatic evaluation is normally disabled because it can be fairly awkward to use (it will often trigger while you’re editing code and evaluate an “incomplete” expression which could well do something unexpected or unwanted) and it only saves you one key chord in most editors anyway since eval form / eval top-level form is usually just a hot key operation.

seancorfield17:05:44

What editor are you using @U02108ERRU5?

Rob Haisfield18:05:05

I’m using IntelliJ with Cursive, but I guess the thing that seems really valuable to me is more just seeing the flow of data through the program moreso than evaluating with a keypress vs. not https://www.youtube.com/watch?v=H58-n7uldoU

seancorfield18:05:27

I don’t think that feature ever made it into a released version of LT — by the time it got out into the wild, it was pretty much a “regular editor” and a lot of the cool features shown off in the early videos had been dropped 😐

Rob Haisfield03:05:50

Ah that’s unfortunate to hear

jaihindhreddy17:05:42

Does the Java standard library contain an impl of top-k (C++ calls it std::partial_sort)? Edit: Looking for a more efficient equivalent of #(take %2 (sort %1))

dpsutton18:05:03

I solved this problem with a bounded size heap:

💯 1
jaihindhreddy18:05:58

Seems like this would fit right-in, in xforms: https://github.com/cgrand/xforms

jaihindhreddy18:05:36

As a transduction no less. Thanks! Was wondering if the Java std lib had it, because it's a (relatively) common operation.

jaihindhreddy18:05:04

That being said, the Priority Queue does much of the heavy-lifting, so that's good to have.

dpsutton18:05:13

yeah. and you can take the idea. i think the priority queue can give you an unordered array or collection of items or you can drain the heap and have sorted results. it's essentially bounded heap sort in that way

✔️ 1
Ivan Koz19:05:34

@julian608 As wise people say. Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.

4
😆 1
BuddhiLW21:05:48

1. What do I do, when I have a n-arrity function and I want to apply partially first other argument than the first? 2. How to pass an argument as the regex, into (str/split <string> <regex>)? I would like to wirte something like this, in which I face (2.)

(defn split-reg [filename reg]
  (->
   (str/split filename #reg)
   (second)))
Then, I want to apply this function in the following manner, in which I think of (1.):
(map #(split-reg % "my-regex") <coll>)

drewverlee21:05:11

I don't believe you can pass the literal syntax. e.g #"..." directly as an argument. There are a couple libraries that seem to get around this limitation, but i wouldn't jump to them if you only have a couple cases. ^ wrong see sean corfields response below

drewverlee21:05:17

Some useful termonology: https://clojure.org/reference/reader#_dispatch The dispatch macro causes the reader to use a reader macro from another table, indexed by the character following The dispatch character is # and the next character in this case is " so it knows it's a regex.

drewverlee21:05:58

regel is a library that would allow for the functionality you want https://github.com/lambdaisland/regal

seancorfield22:05:31

You could either pass the literal regex in as #"my-regex" or you could call re-pattern on a string to turn it into a regex: (re-pattern "my-regex") (although there are some caveats about special characters).

seancorfield22:05:20

So your call would be (map #(split-reg % #"my-regex") <coll>) in the first case — which would be the preferred way to do things.

BuddhiLW22:05:06

My patterns are all numbers and/or letters, generally upper-case. But, I wish to apply it to a lot of different patterns. That would nicely work with re-pattern, I suppose?

seancorfield22:05:56

Yes, if the pattern is a variable string coming from some other code, that would be the better approach.

(defn split-reg [filename reg]
  (second (str/split filename (re-pattern reg))))

(map #(split-reg % some-string) some-coll)

seancorfield22:05:36

dev=> (clojure.string/split "This is a string!" (re-pattern " "))
["This" "is" "a" "string!"]

BuddhiLW22:05:03

That did work great!

(defn split-reg [filename reg]
  (->
   (str/split filename (re-pattern reg))
   (second)))

#'user/split-reg
$ ls |> (map #(split-reg % "teste"))
("1.txt" "2.txt" "3.txt")
Thank you!

1
Stuart22:05:37

Is their a way I can do this:

(defn format-element [element]
  (cond->> (re-matches #"^:\w+$" element)
           (to-register)
           
           (re-matches #"^(:\w+)\[(\d+|\w+)?\]" element)
           (to-reg-array)))
I tried (some->> as well. I want to take a string and do a regex on it, then depending on what re-matches it matches against, pass the resulting matches to a function to format it.

Stuart22:05:07

What I'm trying to avoid is having to do the regex match twice, once to match to know if the string matches then again to get access to the actual matches

Stuart22:05:39

I have this, but feels clunky

(def matchers-and-formatters {#"^:\w+$" to-register
                              #"^(:\w+)\[(\d+|\w+)?\]" to-reg-array})
(defn format-element [element]
  (loop [matchers (keys matchers-and-formatters)
         formatters (vals matchers-and-formatters)]
    (if (seq matchers)
      (let [res (first (re-matches (first matchers) element))]
        (if res
          ((first formatters) res)
          (recur (rest matchers) (rest formatters))))
      element)))

walterl22:05:48

(defn format-element [el]
  (some (fn [[rx fmt]]
          (when-let [match (first (re-matches rx el))]
            (fmt match)))
        matchers-and-formatters))
(untested)

Stuart22:05:41

That seems to work and is nice! I wasn't aware of when-let, I'll need to go read and understand this. Thank you!

👍 1
ghadi22:05:45

if you care about the captures, don't throw them away by calling first

ghadi22:05:55

i.e. pass the whole result of re-matches to the formatter

(defn format-element [el]
  (some (fn [[rx fmt]] (some-> (re-matches rx el) fmt))
        matchers-and-formatters))

❤️ 1
👍 1
ghadi22:05:06

and let the formatter destructure

Stuart22:05:14

Man, i have so much to learn. That's so concise

Stuart22:05:41

Thanks for the help guys, i have stuff to look up (Y)