Fork me on GitHub
#beginners
<
2021-09-09
>
stardiviner00:09:13

How to search in clojurians slack archive? I only saw archiveed channels list. But there is no search input box.

practicalli-johnny06:09:37

There are many ways to get help from Clojure community. I find searching in Zulip the most effective way to look at conversations, including an archive of Slack channels. For example, this query will search the beginners channel for searchphrase

stream:slack-archive topic:beginners searchphrase
https://practical.li/blog/posts/cloure-community-getting-help/

seancorfield01:09:15

Type site: <search phrase> into your search engine.

seancorfield01:09:27

☝️:skin-tone-2: @stardiviner -- or you could go to the Clojurians Zulip (requires an account) and that has a nice, built-in search.

seancorfield01:09:47

FWIW, I don't think the search engine approach is very good via site: since it doesn't have recent conversations. I always use Zulip since it's pretty much real-time.

2
stardiviner01:09:27

Indeed, I tried sometimes now. Only few of results come out. Using Zulip searching now. 😄

Tadeo Uriel02:09:17

hi community, greetings from argentina, i want to learn clojure, can give me some ideas where can i find a free course of this language

adi08:09:46

I'm assuming you already know how to program in some other language, and have some experience writing programs (several hundred lines of code at least). I would suggest tackling this progressively in 3 stages: 1. Minimal key concepts: Take one or two days to work through a hands-on tutorial that introduces you to the most important features, concepts, and mindset. Try to get past things that confuse newcomers to the language. Many tutorials are available at the link I've posted below. Personally, I really like Aphyr's https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome, for this purpose. (And I'm obviously biased, but I also like https://github.com/inclojure-org/clojure-by-example that I helped create and teach :)) 2. Full language feature set + tooling + practical usage: A more comprehensive study (2 - 4 weeks) of the details of the various features of the language, guided by a book. Try to understand how to use the standard library of the language, and also become totally comfortable with a development workflow, language tooling (editor features, linter, REPL, build tool etc.), and get a sense of the library ecosystem. Which book to choose depends on your learning preference and budget. 3. Larger problem-solving and application-building: Follow along expert Clojure programmers as they make apps or solve a variety of problems using Clojure. There are many streams on Twitch and YouTube these days. Also of course, make your own things! Silly projects, fun projects, serious projects; whatever works! Potentially also paid tutorials or workshops, if you want to invest in building a career. Ref: Resources listed at the official website to choose from, for use in each of the stages: https://clojure.org/community/resources#_tutorials_and_learning_materials

✔️ 2
cdpjenkins09:09:45

I learned Clojure from the book Programming Clojure by Stuart Halloway and I got on well with that. There's a third edition of the book out (with two more authors in Alex Miller and Aaron Bedra). I've only read the first few chapters of the third edition but I like what I've read so far.

seancorfield03:09:17

@uriidc A lot of people seem to do well with the free, online version of Clojure for the Brave and True.

2
Nik04:09:35

I started with Clojure for the Brave and True (good example of presentation making content enjoyable). Like Cora said http://practical.li/ has good resources, I generally use it for how-to(s). If you are new to programming in general, try out its development environment setup, so that you can focus on Clojure first. There is http://www.clojurekoans.com (or use http://clojurescriptkoans.com/ online). There's https://purelyfunctional.tv by Eric Normand that, someone recommended. I haven't tried the course yet but his blog was very helpful. Pick any you want (or all? 😄). Welcome to life of Clojure.

seancorfield04:09:00

Yeah, if you're willing to pay for material, Eric's courses are awesome.

4
seancorfield04:09:14

Especially his REPL-Driven Development course, which I just love.

2
Nik05:09:44

hmm, I've been ambivalent about whether to buy or not this particular course. I'll give it a try now

Nik05:09:08

or not... I didn't check the price before. :man-facepalming::skin-tone-3:

seancorfield05:09:17

Yeah, there used to be a $49/month price tier which I think was very affordable -- and I was a subscriber (through my company) for many months -- but the new pricing structure is a bit tough for hobbyist beginners 😞

2
Travis Jungroth14:09:09

@U029PC2K1HV I think there's still a subscription option, but you see it after you create and account, log in and go to your profile. I'd email Eric at <mailto:[email protected]|[email protected]>. He's kind and responsive. Plus, knowing a beginner is getting priced out is good feedback for him.

Nik01:09:27

@U017ANLQXBJ Thanks, will contact him.

valerauko06:09:27

I've got a question but it's rather java than clojure (but I can't seem to find an answer) When writing (lots of) data to a file when does Java trigger the system call to the file? I'd like to minimize the amount of system calls (because with "lots of" data it's an overhead I'm not happy to pay too often), so I'd like to know at most how much data I can write in a single write operation. Or should (can?) I rely on Java's internals handling this fine for me? (I've had trouble with those internals shooting me in the face so my trust in them isn't solid)

practicalli-johnny06:09:10

If you do not get answers here, try the https://londonjavacommunity.co.uk/ who also have a slack community

👍 2
raspasov07:09:13

I haven’t done this level of fine tuning in years, but if you care for maximum performance, I believe one strategy is to buffer a bunch of writes for up to a period of time/max number of entries (say, ~1 ms and, say, 1000 max entries) and at the end of that short period write everything in one shot. That should improve your performance as opposed to flushing/fsync-ing on every write.

raspasov07:09:09

Those numbers are hypothetical, you want to fine tune for your use case: latency requirements, size of those “entries” (whatever they are) are all important to think about. And as with all things performance, exact and repeatable benchmarks are the gold standard. I recommend YourKit for the JVM (no affiliation), it’s an excellent profiler.

👍 2
raspasov07:09:51

For inspiration in terms of achieving good writing performance to a file, perhaps this can be useful: https://github.com/Factual/durable-queue/blob/master/src/durable_queue.clj

raspasov07:09:14

To answer your question directly: you’ll most likely be able to achieve higher write throughput by implementing additional clever+creative buffering at the cost of higher latency and more complex implementation. You have to decide if the trade-off makes sense for your case.

Ed10:09:32

The easiest place to start might be to play around with creating your own BufferedWriter (https://docs.oracle.com/javase/10/docs/api/java/io/BufferedWriter.html) rather than using the default sized one you get from ... that will let you control the flushing to the os a little more explicitly ...

valerauko02:09:09

thanks for the ideas, I'll look around

👍 2
valerauko02:09:12

I have to handle pretty large files pretty often. It doesn't matter if the individual writes are delayed as long as the whole file gets finished quick

adi08:09:46

I'm assuming you already know how to program in some other language, and have some experience writing programs (several hundred lines of code at least). I would suggest tackling this progressively in 3 stages: 1. Minimal key concepts: Take one or two days to work through a hands-on tutorial that introduces you to the most important features, concepts, and mindset. Try to get past things that confuse newcomers to the language. Many tutorials are available at the link I've posted below. Personally, I really like Aphyr's https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome, for this purpose. (And I'm obviously biased, but I also like https://github.com/inclojure-org/clojure-by-example that I helped create and teach :)) 2. Full language feature set + tooling + practical usage: A more comprehensive study (2 - 4 weeks) of the details of the various features of the language, guided by a book. Try to understand how to use the standard library of the language, and also become totally comfortable with a development workflow, language tooling (editor features, linter, REPL, build tool etc.), and get a sense of the library ecosystem. Which book to choose depends on your learning preference and budget. 3. Larger problem-solving and application-building: Follow along expert Clojure programmers as they make apps or solve a variety of problems using Clojure. There are many streams on Twitch and YouTube these days. Also of course, make your own things! Silly projects, fun projects, serious projects; whatever works! Potentially also paid tutorials or workshops, if you want to invest in building a career. Ref: Resources listed at the official website to choose from, for use in each of the stages: https://clojure.org/community/resources#_tutorials_and_learning_materials

✔️ 2
cdpjenkins09:09:10

I have a problem that I'm not sure how best to solve functionally. Does anyone have any ideas? I want to filter a list to remove duplicate elements, without changing the order of the elements that I don't remove. So if X appears multiple time in the list then I want to return a resulting list which contains only the first instance of X. E.g.

(remove-duplicates '(1 2 3 4 1 5 6 2 7 8 1 9)
... returns:
(1 2 3 4 5 6 7 8 9)
I could implement it using a loop/recur, keeping a set of all the elements seen so far, but that feels a little imperative to me and I'm wondering if there's some obvious approach that I've missed.

Maravedis09:09:29

I see a couple of approaches possible. One is if your list is sorted by its content and not arbitrarily ordered, something like https://clojuredocs.org/clojure.core/sorted-set or https://clojuredocs.org/clojure.core/sorted-set-by are probably your best bet.

Maravedis09:09:25

But for strictly what you are asking, I think https://clojuredocs.org/clojure.core/distinct keeps the order of the input ?

jaihindhreddy09:09:55

> but that feels a little imperative to me and I'm wondering if there's some obvious approach that I've missed. distinct does indeed implement it using recur, and also can return a transducer. So, in a sense, you're thinking of re-implementing distinct. You can simply use distinct and get laziness for free as well. And if you explicitly don't want laziness, you can use (distinct) the transducer.

cdpjenkins10:09:44

Nice, it looks like distinct is indeed what I want. (Can't believe I missed it!) Many thanks. I'll give it a try when I get back to the computer.

Ed10:09:38

just to add a point about transducers ... with transducers, lazyness is optional at the point of application. So if you write

(into [] (distinct) [1 2 3 4 1 5 6 2 7 8 1 9])
it will eagerly produce a vector, but
(sequence (distinct) [1 2 3 4 1 5 6 2 7 8 1 9])
will return a lazy-seq which filters out duplicates. I only mention this cos I'm starting to feel that transducers are distinctly better than lazy-seqs in several ways and think it's a good thing for people to learn 😉

✔️ 4
👍 4
Benjamin09:09:25

what is a good way to take a map and return a map with the same keys and transformed keys?

Benjamin10:09:07

thanks, my code now

(defn update-vals [map f]
  (reduce
   (fn [coll [k v]]
     (assoc coll k (f v))) {} map))

(update-vals @data count)

Ed11:09:29

there's also update which takes a map and runs a function on a key to return a updated map, so

(update {:a 1} :a inc) ;; => {:a 2}
which you could use instead of (assoc coll k (f v)) if you passed in the map as the second argument to reduce, maybe like this?
(defn update-vals [m f]
  (reduce #(update %1 %2 f) m (keys m)))
another way to write this would be using a transducer like this:
(defn update-vals [m f]
  (into {} (map #(update % 1 f)) m))
however, this comes up so often, that apparently a core implementation is coming soon : https://ask.clojure.org/index.php/1926/adding-functions-map-vals-and-map-keys

👍 2
peter hull12:09:40

You could also (defn update-vals [coll f] (into {} (map (fn [[k v]] [k (f v)])) coll)) or (defn update-vals [coll f] (reduce-kv #(assoc %1 %2 (f %3)) {} coll))

❤️ 2
walterl10:09:02

I forgot about reduce-kv!

roelof13:09:50

why is this code not return :equal when I compare two empty list

(ns sublist)

(defn classify [list1 list2]
  (cond (= list1 list2) :equal )
         ((clojure.set/subset? list1 list2) :sublist)
         ((clojure.set/subset? list2 list1) :superlist))

Fredrik13:09:18

The clauses in cond are not written they way cond expects them to be written

roelof13:09:15

oke, then back to the docs to see what it should be

Fredrik13:09:59

Also a heads up: The clojure.set functions generally expects to be passed sets as arguments, not lists. This is often a point of confusion, because sometimes they seem to work with lists, even though that is just an accident of their implementations.

roelof13:09:42

oke, so I have to convert them to sets or write some own code to check if a list is a super or sublist

roelof13:09:02

hmm then I have to think well how to do so

Fredrik13:09:19

There are many ways to compare lists and other "sequential" things. If you don't care about comparing the ordering of items within the lists, you can convert them both to sets and use the clojure.set functions

Fredrik13:09:38

If this doesn't make sense or you need more help, just shout out 🙂

roelof13:09:03

oke so

(clojure.set/subset? (set list1) (set list2)) :sublist

Fredrik13:09:06

Assuming you don't care about ordering, this does exactly what you want.

Fredrik13:09:04

For the other direction, there is a built-in clojure.set/superset , which you can use instead of swapping the arguments, to make the intent in your code even clearer

roelof13:09:53

oke, thanks for the help so far

roelof13:09:04

the exercism ide is still not happy

Fredrik13:09:42

Does the exercise care about ordering perhaps?

roelof13:09:35

oops back to the drawing table then

tschady14:09:50

your parens are wrong in first code paste. you close around cond on the first line.

Maravedis14:09:31

I feel stupid asking this, but is there a function in core that is the complement to not-any? ? Because any? just sends back true.

Ed14:09:43

some? ... as in

(not-any? #{2} [1 2 3])
  (some #{2} [1 2 3])

Maravedis14:09:30

Doesn't some send back nil if it is not contained ?

Maravedis14:09:41

I know nil is falsey, but i'd rather have false.

Ed14:09:59

you could always cast it to a boolean after with

(boolean (some #{9} [1 2 3]))
I would use some ... tbh ... and not worry about casting it ...

Maravedis14:09:11

That's what I'm doing. It just tickles me the wrong way.

Ed14:09:20

I think that any? was added for clojure.spec to have a predicate that always returned true, so it would allow all values when checking data.

Ed14:09:08

why does it tickle you the wrong way?

delaguardo14:09:42

(some #{false} [false 2 3])
as an example when it could return “wrong” result

👍 2
Ed14:09:12

👍 ... fair point

Ed14:09:14

in that case though, wouldn't you write

(some false? [1 2 false 4])
?? ... cos it's using the set as a predicate that's making the false value a problem???

delaguardo15:09:17

sure, the strategy has a strong dependency on the data

emccue15:09:13

@U02DEQJ409F Have you tried (complement not-any?)

Maravedis15:09:51

But wouldn't that read the whole input when I want to fail fast and inversely ?

((complement not-any) #(not (= 7 %)) [1 2 3 4 5]) => must read the whole coll before saying nothing is equal to 7, then take the complement
(fantasy-any? #(not (= 7 %)) [1 2 3 4 5]) => fails on 1

Ed15:09:31

isn't that

(every? #(= 7 %) [1 2 3 4 5])
????

Maravedis15:09:55

Oh yeah it is, bad example from me then.

emccue15:09:55

Just personally, if it might have to read every element i don't mind it always reading every element

emccue15:09:19

at least its consistent

Ryan15:09:01

I am filtering a list, and need to dynamically assemble some filters based on a map (e.g. {:favorite true :active false :has-foo true}) .. whats a good way to do that? Each filter value has a predicate associated.

Ed15:09:39

you could make the filter like this:

(let [my-list  [{:a 1 :b "test"} {:b ""}]
        pred-map {:a true :b false}
        filt     (->> pred-map
                      (keep #(when (val %) (filter (comp some? (key %)))))
                      (apply comp))]
    (sequence filt my-list)) ;; => ({:a 1, :b "test"})
does that make sense?

Ryan15:09:19

the map is coming from a reframe db that represents the ux state of the filter controls