Live data from Hacker News

Clojure by Example (2015)

kimh.github.io

31–40 of 46 posts

Re: Clojure by Example (2015)

#31
post #18
post #6

Learning a new language by mapping constructs from another language you know better is certainly expedient. But the trade off is you short change yourself on learning core philosophical beliefs underpinning the design of the language. Understanding these poorly means you will not exploit the language very well and arguably should just stick with the prior language. Clojure more than most languages is built around som…

Are there any other resources that you'd recommend to people coming from languages like Python or JavaScript? I'm assuming 'Clojure for the Brave and True'?

Found walking through exercises of Clojure Koans useful

Re: Clojure by Example (2015)

#32
post #27
post #5

> Clojure doesn't provide built-in function for exponential operation It does actually: (Math/pow 2 3) ;;=> 8

`Math/pow` is not a function. If it were, you would be able to do things like this: (map (partial Math/pow 2) [0 1 2 3])

"Math/pow" is actually a function on JVM level. Clojure functions are objects with special callable method.

This will work: (map (partial #(Math/pow %1 %2) 2) [0 1 2 3])

Re: Clojure by Example (2015)

#33
post #8
post #5

> Clojure doesn't provide built-in function for exponential operation It does actually: (Math/pow 2 3) ;;=> 8

The very next sentence of the article points out that you can leverage Clojure's interop to invoke Math.pow(), but that's still limited to casting its arguments down to java.lang.Double and suffering the limits therein If you instead used the library org.clojure/math.numeric-tower [1] you can get much more precise answers, for example # start a repl with an extra dep $ clj -Sdeps '{:deps {org.clojure/math.numeric-tow…

You need to be familiar with Java types and differences between them (Integer, BigInteger) and how Math.pow() behaves with different types. This is more up to Java, rather than Clojure.

No need to pull the library for this, Clojure already has (biginteger) for that:

    user=> (.pow (biginteger 33) 33)
    129110040087761027839616029934664535539337183380513

Re: Clojure by Example (2015)

#34
post #33
post #8

Earlier quoted context omitted.

The very next sentence of the article points out that you can leverage Clojure's interop to invoke Math.pow(), but that's still limited to casting its arguments down to java.lang.Double and suffering the limits therein If you instead used the library org.clojure/math.numeric-tower [1] you can get much more precise answers, for example # start a repl with an extra dep $ clj -Sdeps '{:deps {org.clojure/math.numeric-tow…

You need to be familiar with Java types and differences between them (Integer, BigInteger) and how Math.pow() behaves with different types. This is more up to Java, rather than Clojure. No need to pull the library for this, Clojure already has (biginteger) for that: user=> (.pow (biginteger 33) 33) 129110040087761027839616029934664535539337183380513

Didn't Clojure use the N suffix for big integers at one point? I don't see one on that output.

Re: Clojure by Example (2015)

#35
post #16
post #13

There are a few things I would like to see added as I have found them very useful in day to day work with Clojure(Script). cond-> and cond->> which takes an expression and then threads it through test/form pairs without short circuiting by stopping on the first test that returns true. I have used this a lot when conditionally adding to maps. Something like this: (let [base-map {:id "123"} name (function-that-could-re…

I see this kind of map update code usually written using merge, like this (ignoring DRY itch for now) (merge base-map (when name {:name name} (when address {:address address}) Or to avoid repeating field names, just form one map to be merged like {:name (function-that-may-return nil) :address (function-2)} and filter out nils from the map before merging that with-base-map. I guess with cond-> you have the advantage t…

Yea I used to do the merge and when as well. I'm not sure if there is an idiomatic way to do it but I personally prefer the threading style as it is "prettier".

Re: Clojure by Example (2015)

#36
post #18
post #6

Learning a new language by mapping constructs from another language you know better is certainly expedient. But the trade off is you short change yourself on learning core philosophical beliefs underpinning the design of the language. Understanding these poorly means you will not exploit the language very well and arguably should just stick with the prior language. Clojure more than most languages is built around som…

Are there any other resources that you'd recommend to people coming from languages like Python or JavaScript? I'm assuming 'Clojure for the Brave and True'?

At work we would give new hires "Living Clojure". There is also the site https://www.4clojure.com/ if you are looking to do some exercises.

Re: Clojure by Example (2015)

#37
post #33
post #8

Earlier quoted context omitted.

The very next sentence of the article points out that you can leverage Clojure's interop to invoke Math.pow(), but that's still limited to casting its arguments down to java.lang.Double and suffering the limits therein If you instead used the library org.clojure/math.numeric-tower [1] you can get much more precise answers, for example # start a repl with an extra dep $ clj -Sdeps '{:deps {org.clojure/math.numeric-tow…

You need to be familiar with Java types and differences between them (Integer, BigInteger) and how Math.pow() behaves with different types. This is more up to Java, rather than Clojure. No need to pull the library for this, Clojure already has (biginteger) for that: user=> (.pow (biginteger 33) 33) 129110040087761027839616029934664535539337183380513

Yeah if you know you're definitely dealing with integers that are large, and are willing to pay the cost to promote into biginteger territory, that's certainly a way to do it with the stdlib.

The nice ergonomic thing about clojure.math.numeric-tower is you can shove any of the Clojure numeric types at it (longs, doubles, but also Ratio or BigNum etc) and it'll intelligently handle the various combinations of types in order to give you the best answer it can

Re: Clojure by Example (2015)

#38
post #13

There are a few things I would like to see added as I have found them very useful in day to day work with Clojure(Script). cond-> and cond->> which takes an expression and then threads it through test/form pairs without short circuiting by stopping on the first test that returns true. I have used this a lot when conditionally adding to maps. Something like this: (let [base-map {:id "123"} name (function-that-could-re…

Another two functions that I forgot to mention last night are filter and keep. I am actually surprise filter isn't already on the site.

filter takes a predicate and a collection and will return a lazy sequence of all items that the predicate returns logically true. For example:

  (filter odd? [1 2 3 4])
would return a lazy sequence of (1 3)

keep is a function that I was unaware of (and most of my team was too) until I was turned on to it by a former coworker. keep takes a function and a collection and returns a lazy sequence of non-nil results. For instance, if I have a collection of maps and I want to only get a value of a specific key I could do the following with map and remove

  (def items [{:v "hi"} {:v "there"} {:m "not v"}])
  (remove nil? (map :v items))
What the map does is get the key `v` from each map in the collection and we end up with a sequence that looks like `("hi" "there" nil)` Since the last map in the collection `items` does not have a key `v` the value will return nil. We would then need to use the remove function with the nil? predicate which will remove all items in the collection that are nil. If we use keep, though, we could do this in one pass.

  (def items [{:v "hi"} {:v "there"} {:m "not v"}])
  (keep :v items)
Because keep already removes nil for us we end up with `("hi" "there")`

Re: Clojure by Example (2015)

#39
post #18
post #6

Learning a new language by mapping constructs from another language you know better is certainly expedient. But the trade off is you short change yourself on learning core philosophical beliefs underpinning the design of the language. Understanding these poorly means you will not exploit the language very well and arguably should just stick with the prior language. Clojure more than most languages is built around som…

Are there any other resources that you'd recommend to people coming from languages like Python or JavaScript? I'm assuming 'Clojure for the Brave and True'?

I maintain a github repo where I implement the same feature identical rudimentary news feed microservice in different programming languages and frameworks. Here is the social broadcast function in clojure.

https://github.com/gengstrand/clojure-news-feed/blob/master/...

and in python

https://github.com/gengstrand/clojure-news-feed/blob/master/...

and in node.js javascript

https://github.com/gengstrand/clojure-news-feed/blob/master/...

That last one is pretty old and predates async and await.

Re: Clojure by Example (2015)

#40
post #28

Personally I've had great success working slowly with an open babashka repl through the tutorials from aphyr: https://aphyr.com/tags/Clojure-from-the-ground-up - everything else didn't really stick for me, but I probably didn't invest enough time. Especially the first few articles helped a lot to clear up misconceptions for a newbie to lisp. I remember reading the linked article but it didn't worked for me.

The aphyr series I think is the best one for a quick intro to Clojure.
Post reply on HN