Fork me on GitHub
#beginners
<
2018-06-05
>
naijeru01:06:34

how do i convert a seq into a map? basically turn (:key1 val1 :key2 val2) into {:key1 val1 :key2 val2} so I can access values by keyword?

noisesmith01:06:36

(apply hash-map s) would do that

naijeru02:06:11

i’ve tried that, but it doesn’t seem to return what i need, doing this (reduce into (map #(hash-map (first %) (last %)) s) does work but it feels clunky

naijeru02:06:47

well since i got it working i’ll move on to other things and hopefully discover a better way of handling this, thx

dpsutton02:06:50

oh so s is a sequence of tuples?

dpsutton02:06:41

(apply hash-map [:a 1 :b 2 :c 3]) => {:c 3, :b 2, :a 1}

dpsutton02:06:29

(into {} (map vec '((:a 1) (:b 2)))) => {:a 1, :b 2} if they are tuples

hiredman02:06:51

(into {} (map vec) ...)

hiredman02:06:32

but given the example, apply hash-map should definitely do it

seancorfield03:06:59

@chris568 (into {} (map (juxt first last)) s) should be equivalent to the reduce into you posted but I think is less clunky?

seancorfield03:06:34

user=> (def s [[:a 1] [:b 2] [:c 3]])
#'user/s
user=> (into {} (map (juxt first last)) s)
{:a 1, :b 2, :c 3}
user=> 
if that's what your s looks like?

_rj_r_03:06:59

I cannot wait until I get better with this language! I'm doing codewars with Clojure...and solved a problem with this:

(defn accum [s]
  (let [cnt (inc (count s))]
    (loop [res []
           s s
           curcnt 1]
      (if (= curcnt cnt)
        (apply str (interpose "-" res))
        (recur (conj res (clojure.string/capitalize (apply str (repeat curcnt (first s)))))
               (rest s)
               (inc curcnt))))))
And then saw other people's answers... one of which is this:
(defn repeat-capitalize [i elm]
  (capitalize (apply str (repeat (inc i) elm))))

(defn accum [s]
  (join "-" (map-indexed repeat-capitalize s)))
I'm doing things the hard way 😕

dpsutton03:06:50

(into {} [[:a 1] [:b 2]]) => {:a 1, :b 2}. if you have vectors your life is easier

seancorfield03:06:07

@dpsutton Yeah, I was sort of assuming he had something a bit more complex than just sequence of pairs -- given his original question was about an alternating sequence of keyword/value for which apply hash-map should have worked...

seancorfield03:06:29

@ryan.russell011 A good rule of thumb is: if your first solution is loop/`recur`, then there's probably a more idiomatic solution 🙂

seancorfield03:06:15

(but loops are so common in other languages that it's often hard, at first, to get past that approach)

_rj_r_03:06:14

@seancorfield I was just thinking about that actually. Old habits are hard to break at the moment.

br04:06:24

After a hand-holding clojurescript testing tutorial... any recommendations?

hawari06:06:46

Hi everyone, so I have a map that is structured roughly like this

{:collections [{:collection-id 1
                        :items [{:item-id 11}
                                {:item-id 12}]}]}
How can I apply a function into each of the items in a collection?

hawari08:06:12

Nevermind @tthock, I've just found Specter, and I must say, it is one heck of a library https://github.com/nathanmarz/specter

John Maruska15:06:09

In case you didn't know, there's a #specter channel specifically for this library

hawari06:06:52

Yes, thank you @U8VJYTQ76 I did joined the channel after finding the library

iyerland11:06:08

Hello everybody, newbie here ... any recommendations on a great book/article for closure? Thanks!

val_waeselynck12:06:04

@narayan Welcome! I suppose you mean "Clojure"? 🙂 ("Closure" is another tool that is involved in ClojureScript)

val_waeselynck12:06:50

To get good recommendations, you should tell us a bit more about your experience / background in programming

naijeru12:06:57

@seancorfield your supposition is correct, i should have asked my question with more specificity

iyerland13:06:52

@val_waeselynck Thanks! Yes I meant Clojure 🙂! Around 20 years of server-side experience, last 5 in Scala/FP. Eager to learn Clojure :+1:

val_waeselynck13:06:47

OK, I also came to Clojure from Scala, so what worked for me will probably work for you

val_waeselynck13:06:58

The book "Programming Clojure" is pretty good

iyerland14:06:27

Actually forgot to ask ... why do you like this book? Plenty of examples, example driven etc? Please let me know. Thanks!

val_waeselynck14:06:15

I'd just say "well explained" 🙂

val_waeselynck14:06:44

Not especially examples driven, it explains the concepts well.

sundarj18:06:13

also going to recommend Joy of Clojure since you're experienced; i've heard good things about Clojure Applied as well (going to be reading that one soon)

val_waeselynck13:06:36

You can use that to learn the language, then maybe move on to "Web Development with Clojure" to build something hands-on

iyerland13:06:20

Isin't Web Development in Clojure out-dated, release almost 2 years back?!

val_waeselynck13:06:21

Probably a bit, but even if it was released yesterday, you may not agree with every choice of the author. What's important is that you get some hands on experience and learn to find your footing in the ecosystem. After that, you'll decide for yourself what libs to use to build a project

iyerland14:06:34

Makes sense :+1:

val_waeselynck13:06:33

Finally, do read the language reference (https://clojure.org/reference/reader) after the first book, it's not that long

val_waeselynck13:06:09

@narayan P.S: for learning, use the REPL! Programming in Clojure is a very "live" experience compared to Scala.

iyerland13:06:06

@val_waeselynck Thanks! I agree ... feedback is quick in Clojure, and am enjoying it 🙏

iyerland14:06:56

Absolutely!

troglotit13:06:11

Kinda lazy web: what’s the f for (= (f sum [1 2 3] [4 5 6]) [5 7 9])?

troglotit13:06:47

Oh, yeah, somehow I thought about map, but discarded it. Thanks!

bronsa13:06:20

assuming sum == +

_rj_r_21:06:57

So for those that were discussing coming from Scala to Clojure? Why the switch? How does your experience with Clojure differ from Scala?

seancorfield22:06:53

Happy to discuss 🙂 @val_waeselynck You also said you came from Scala to Clojure. Should be an interesting thread.

seancorfield22:06:33

I tried to introduce Scala at World Singles when I first joined (2009) because they had some problems where the solutions would be long-running background jobs that a) needed to produce XML and b) would require a lot of concurrency. So Scala looked like a good choice with XML literals and actors.

seancorfield22:06:42

It was successful, insofar as it solved the main problems better than anything they had previously tried. However, it was back in the 2.7 days and the actor library had known memory leaks, so we had to restart the process every few days. Annoying but livable.

seancorfield22:06:39

So I started to explore using Scala more extensively at work but also the 2.8 release was in progress and every single milestone release broke binary compatibility so we had to upgrade the entire tool chain each time -- which was extremely painful. The Scala folks promised this was a lot of one-off breakage and wouldn't happen again -- but the upgrade to 2.9 was much the same (we stopped trying to upgrade at that point).

seancorfield22:06:06

Things we liked: XML literals, immutable data, powerful collection library. Things we were on the fence about: the type system. Things we disliked: slow compiler, brittle tool chain (as far as upgrades were concerned), horrible compiler messages. Ultimately, the slow edit-compile-test-deploy lifecycle was just too painful, given the history of dynamic languages at the company.

seancorfield22:06:54

And the type system... when it works, it works really well. When you get something wrong -- especially anything that involves implicits -- you get a wall of compiler errors and it's not always clear what's wrong or how to appease the type checker. Since the collection library leverages implicits a lot, pretty much anything you did wrong with collections tended to induce a lot of head scratching.

seancorfield22:06:15

In 2010, I started playing with Clojure and by 2011 felt confident enough to rewrite our concurrent, XML-heavily background process in Clojure. The code was substantially shorter than the Scala (more on that in the next message) and was rock solid in production -- no memory leaks -- but it ran quite a lot slower at first. After some experimentation, I got it running faster than the Scala version (by adding more concurrency, as it turned out, which was just easier in Clojure, IMO).

seancorfield22:06:11

Given the Scala code's heritage, I didn't have much to leverage in terms of SQL abstractions so I wrote some of my own and that added to the relatively bulk of the Scala code compared to Clojure. In Clojure, java.jdbc meant that queries gave me plain ol' Clojure data structures (sequences of hash maps) and I could insert plain ol' Clojure hash maps as records -- no abstraction layer needed.

seancorfield22:06:02

For the XML stuff, we used Hiccup so we maintained nearly all of the benefits of Scala's XML literals as Clojure data.

seancorfield23:06:32

And the slow edit-compile-test-deploy cycle went away completely with Clojure (we use clojure.java.api to "embed" Clojure into our legacy apps which allows us to deploy as source and have the full connected-REPL, code reloading experience -- as we slowly rewrote our legacy codebase from the bottom up in Clojure).

seancorfield23:06:01

Happy to answer any additional questions you may have based on that!

_rj_r_01:06:59

I find it interesting since I have met people on the Scala side that swear by it... (granted they are on 2.12 now)... I have little experience with either.. and have read quite a bit regarding both (mostly how Scala got to be more popular than Clojure... from what I can tell it is mostly a syntax thing since it is more closely related to Java)....

rt8501:06:59

@seancorfield thanks for your sharing.

_rj_r_01:06:43

But I have yet to get a straight answer as to the "why" .. and that was an excellent breakdown in regards to your history and experience on both sides.

_rj_r_01:06:48

not sure if you have experience with 2.12... I'd be curious to know if they actually fixed many of the Scala issues you pointed out...

seancorfield02:06:12

I think a lot of it is down to Scala being marketing as a "better Java" and it can be used as "just" that -- a more powerful OOP language with some immutability -- or it can be useful more like Haskell (ScalaZ etc).

seancorfield02:06:47

I think Scala is a fascinating language, and if I had to write it all day for a job, I'd probably be happy enough. I find it very telling tho' that Odersky is working on Dotty to provide a simpler type system for inclusion in Scala 3.x...

_rj_r_02:06:42

true.. although from my rather (very) limited experience with Clojure.. I actually feel like it could fill that role just as well, if not better in some regards.

_rj_r_02:06:38

I tried to learn Scala.. and it just didn't feel right to me in a lot of ways... not that I by any means did anything complex with it.. but it felt like it didn't have its own identity.. like it was trying to be too many things at once.

seancorfield02:06:00

I don't know what the status is with the actor library -- I thought they were replacing it with a version of Akka? And I know that compiler speed is an area of continual improvement (incremental compiling is a thing for Scala now, I believe?).

seancorfield02:06:51

Clojure is far too alien to go mainstream tho'. A Java developer learning Scala can still use mutation and objects and loops. Moving to Clojure requires a fairly seismic shift in thinking.

seancorfield02:06:45

But I've been a Clojure developer professionally now for seven years and I'm very happy with that choice.

_rj_r_02:06:14

yeah I don't see many Clojure dev jobs out there. My current job is in the government sector.. so Java code bases and proprietary languages at the moment...

seancorfield02:06:47

You probably see some ColdFusion too in government?

_rj_r_02:06:37

no, not on the project I am on

val_waeselynck06:06:59

@ryan.russell011 @seancorfield My story: I had been programming in Java for years, and was really fond of it (my first language!). However, although I felt like I mastered it, I also felt to slow when programming in it - abit like running underwater: you see exactly where you're heading and how you will get there, but it's just to slow. So I started looking for a more expressive language. I surveyed the other languages on the JVM, and because I was still a bit naive at the time, I assumed the best choices would be the more popular (at the time: Groovy, then Scala, then Clojure)

val_waeselynck07:06:00

I was quickly disappointed by Groovy, then Scala felt really promising, I was really enthusiastic. I studied it, did a project with it, and found an internship in it (I was still a student at the time). A few months later, I was also disappointed with Scala; I felt it had not eliminated the limitations of Java, just pushed them a little farther away, but I still ran into them eventually. More importantly, I was not happy with the 'too many features' of Scala and the impact it had on its ecosystem: it was like every library author would design software as if playing Bingo ("need to add Feature X? Okay, let's see if I can do that with traits, implicits, higher-kinded types, XML literals and the Cake pattern."). The way I see it, this led to a combinatorial explosion of not very compatible ways of programming.

val_waeselynck07:06:11

In the meantime, doing some frontend work in JavaScript (in a "JavaScript, the Good Parts" spirit) had opened my eyes on how functional programming with dynamic typing and generic data structures could be a very effective way to program. So I decided to give Clojure a second chance, and was blown away by the expressiveness of the language, its minimalist and pragmatic mindset (Rich Hickey talks made me think "wow, this guy is more lucid than any other thought leader I've encountered in the software world, I wanna use what he made"), and more importantly the interactive workflow of the REPL. Haven't found that anywhere else since.

val_waeselynck07:06:17

One metaphor I have in mind is: if Java was a balloon, Scala would be a zeppelin, and Clojure would be a plane. When you're looking for a better balloon, the zeppelin is the more natural choice, and the plane seems to have unacceptable limitations (can't stay in the air without moving, huge landing runways, etc.). When you take a step back, and are actually looking for a better way of flying, you may consider the plane!

val_waeselynck07:06:45

I'm curious to give Scala a new try, but I'm even more attracted to Haskell, OCaml etc. It seems to me now that classes in Scala are just useless baggage (useless in terms of inherent value, not in terms of appeal to mainstream programmers).

seancorfield13:06:09

Thanks @val_waeselynck ! I definitely agree on the "too many features" aspect of Scala but I hadn't thought of it as just pushing Java's limitations further out -- very insightful! Interesting to hear you mention Groovy as I also did time with that prior to Scala. I really liked Groovy -- as a low ceremony version of Java -- but agree that it doesn't bring much that is novel to the table. My main disappoinment with Groovy was simply that it just didn't seem to be going anywhere -- it almost felt abandoned.

seancorfield13:06:54

I try to follow the Pragmatic Programmer's advice and learn a new language every year. That's meant Go, Rust, Elm, and Kotlin over the last four or five years. I like Elm but find it very constraining. I like Rust but it's a complex language. I like Kotlin but it's just "a better Java" with nothing really new. I was disappointed with Go (I guess I was hoping for Rust but I didn't know that until I learned Rust later!). None of them have the elegance and expressiveness of Clojure though.

val_waeselynck14:06:21

I would love to try Rust, I just don't have enough low-level stuff to do. Maybe I'll rewrite the artificial life program I made in Java a few years ago and see how much faster I can make it.

seancorfield15:06:51

Yeah, that's always the hard part, for me, of learning new languages: trying to find something worthwhile to build with them to make the learning useful.

iyerland22:06:13

My experience: I started out with C++/OOP/Java for the first 15 years, somehow my intuition did not buy the bloated classes with loads of inheritance! But I did not know how to fix this! When I learnt FP (Erlang/Clojure/Scala), I thought that is what I have been yearning all my life! Even in my OOP days, my solutions were like FP, and even got rejected in interviews due my FP-biased responses in the OOP days, as it was not clearly OOP! I was able to focus on FP/Scala for the next 5 years, and enjoyed it ... till I faced way too many abstractions, types creating too much structure ... monadic abstractions over-shadowing business logic, top-down explosion! I am enamored by the minimalism of Clojure and hope to explore and exploit its full potential, and use it as my go-to modeling/prototyping language, even though there's a high possibility, I may never get the opportunity to professionally use it at work in production environment! I like the bottom-up approach and the data as api approach (still learning and hope to learn more in days/months/years to come)! In my opinion the biggest obstacle for Clojure, is that it is too good! You can build your own web-service framework and use the various libraries (noir/compojure/ring) like lego pieces, so much so there is no consensus in the community! This is self-defeating, in that a successful language (based on my observation), needs to have some level of toughness and opaqueness for engineers to sweat and toil and suffer and feel delighted to solve it through nightmarish ways and feel exalted, and they share with others how they enjoyed (strangely) it 🙂 ! A successful language needs a go-to clear consensus framework for web development! Clearly Clojure is unqualified if we measure it using these yard-sticks! And yet, these are exactly, reasons why sane engineers like and feel attracted to Clojure. Oh and yes the parens do keep a lot of programmers/engineers away! There you go 😄!

seancorfield23:06:52

Clojure doesn't quite follow Haskell's mantra of "Avoid success at all costs!" but it certainly doesn't pander to any popularity contests :rolling_on_the_floor_laughing:

_rj_r_00:06:33

@seancorfield Yes... Rust is incredibly complex at times. My capstone project for school (I've been graduated for almost a year now) was an embedded core OS, serial driver, and DMA driver... written in Rust. Luckily we had a guy on our team that was quite good with Rust so that helped a lot, especially when running into the "borrowing/ownership/lifetimes". I really wanted to continue and learn more Rust... but just haven't gotten around to it. I have huge respect for the language though, and from my short interaction with it... I have quite a bit of respect for the devs are fluent in it. It tells me they spent a lot of time caring about what their code does, and why it is doing it.

iyerland01:06:31

@seancorfield True that! Another pattern I want to share .. when I was into Scala, I made it a point to follow the practitioners/speakers on Twitter, and my tweetline was bombarded with all theories (monads galore, higher kinded types, kleisli etc), I could never completely read them! When I made Clojure my focus, I unsubscribed from all things Scala, and restricted to Clojure ... and what a sea-change! Communities have personalities too ... very much inspired and influenced by the language and the creator of the language, for good or for bad! No conclusions here, just observations.

3Jane22:06:26

If I use deftype, what’s the standard way to add testing for equivalence to the newly defined type?

3Jane22:06:23

(Clojure, not Clojurescript)

noisesmith22:06:43

so you want to override =?

3Jane22:06:15

(I know that if I used defrecord, that would be built in)

noisesmith22:06:41

(ins)user=> (deftype Foo [] Object (equals [x y] true))
user.Foo
(ins)user=> (= (Foo.) 1)
true
(cmd)user=> (= (Foo.) 2)
true

noisesmith22:06:48

it's built in to deftype as well

3Jane22:06:55

I found this article http://blog.klipse.tech/clojurescript/2016/04/26/deftype-explained.html but it seems clojurescript-specific

noisesmith22:06:05

(ins)user=> (deftype Bar [x] Object (equals [x y] (= (.x x) (.x y)))
)
user.Bar
(ins)user=> (= (->Bar 1) (->Bar 1))
true

noisesmith22:06:25

if you implement equals you should also implement hashCode and compareTo

noisesmith22:06:24

also that's a bad equality predicate - you probably want to return false for all things that are not a Bar for example

3Jane22:06:02

yes, I do do type checking

3Jane22:06:31

your example works, but adding it to my existing type doesn’t. However, that gives me something to go on to experiment. Thank you! 🙂

dpsutton22:06:37

you shouldn't call (.x y) until you're certain that the y is a Bar (or has some .x property i guess)

noisesmith22:06:50

right, I kind of meant that

dpsutton22:06:00

yeah. just passing on for @lady3janepl

noisesmith22:06:14

> also that's a bad equality predicate - you probably want to return false for all things that are not a Bar

dpsutton22:06:25

interesting, if you have already def'ed something like Foo, deftype Foo throws with weird messages

3Jane22:06:48

I must have had some old definitions left over - after a reload, it’s working 🙂

3Jane22:06:28

compareTo for collections would be … weird.

3Jane22:06:48

(I’m checking if I can implement data structures from Okasaki’s book, for the heck of it. I know someone’s already done it; I don’t want to peek since it’s a good motivator to learn the language better)

noisesmith22:06:08

clojure collections do compareTo

noisesmith22:06:36

iirc java ones do too

noisesmith22:06:40

user=> (compare [:a] [:b])
-1

3Jane22:06:48

huh. by length or by head value?

noisesmith22:06:49

you can sort a coll of colls, why not?

noisesmith22:06:06

length first, then head, then second item, etc.

3Jane22:06:07

I guess for a list you’d just recursively compare every item (since to calculate length you have to traverse the list anyway)

3Jane22:06:03

is there a simple expression that would be the equivalent of x or y, where if x is falsey (0 in this case), y will be evaluated?

3Jane22:06:34

0 is not falsey in Clojure, so (or x y) doesn’t work in the same way

yogidevbear23:06:40

My brain is very tired and I'm sure there are more elegant options, but something like (or (and x (not (= x 0))) y) maybe?

noisesmith23:06:27

evaluated or is just returned good enough?

noisesmith23:06:51

if you aren't doing it for side-effects (#{0} y x) works

noisesmith23:06:49

user=> (map #({0 %2} %1 %1) [0 1 0 1] [:a :b :c :d])
(:a 1 :c 1)

noisesmith23:06:55

that's weird code

3Jane23:06:49

my best idea: (drop-while zero? [x y z...])

3Jane23:06:19

but that’ll evaluate all of x, y, z (which I’m trying to avoid)

noisesmith23:06:35

oh, so you do care about the side effects

3Jane23:06:09

well basically I want to do a (simple expr) or (recursive expr) and I want to short-circuit if the first one is not-zero

3Jane23:06:27

(…yes, this is all a comparator followup XD )

noisesmith23:06:43

yeah, I'd use if for that, optionally in a macro if you think it deserves a syntax

noisesmith23:06:45

you can even do an optimized recur from an if branch

3Jane23:06:51

and with this, good night! I just looked at the hour and :woman-facepalming:

3Jane23:06:05

further weirdness will resume… in due time