clojure-sg

http://www.meetup.com/Singapore-Clojure-Meetup/
2017-05-25T02:16:42.405589Z

http://tonsky.me/blog/readable-clojure/

2017-05-25T02:17:43.413255Z

Generally good suggestion, although I can not agree with "avoid high-order functions"

spinningarrow 2017-05-25T02:25:34.473289Z

Yes same here. I actually think his example using comp looks more readable than the one using anonymous functions

lucasbradstreet 2017-05-25T02:26:38.481500Z

My thoughts exactly

2017-05-25T03:42:56.014278Z

Agree here. I use comp more and more often instead of nested anonymous function. Especially when I need argument function for filter, remove, sort-by, juxt, etc comp can be used to convert deeply nested function calls to a concatenation of self-contained functions. The other way to makes it easier to read is to use threading macro at the first position, but it still looks weird to me. For example, I would rather prefer comp here

(->> {1 {:id 1 :product {:name "Macbook Retina"}}} 
     (map (juxt key (comp #(str/replace % " " "-") str/lower-case :name :product val)))
     (into {}))
; => {1 "macbook-retina"}
more than
#(str/replace (str/lower-case (:name (:product (val %)))) " " "-")
or
#(-> % val :product :name str/lower-case (str/replace " " "-"))

2017-05-25T03:47:50.045941Z

threading macro approach would get a bit messier when we need to mix -> and ->>

2017-05-25T03:47:51.046076Z

I would probably create a function extracted-name or something like that which would use the threading macro and the map would just call the function šŸ˜‰

spinningarrow 2017-05-25T03:48:17.048722Z

Yesss. Self documenting code for the win šŸ˜‰

2017-05-25T03:52:38.077670Z

Thatā€™s an option but I think itā€™s not always. I find myself less strict with descriptive name when I have pure functions and repl. I try not to overly create a new functions these days. Itā€™s easy to run/play with a piece of code than dealing with naming confusion and conflicts to me šŸ˜‰

spinningarrow 2017-05-25T03:56:43.104152Z

Do you usually write code in the repl and then move it over to your source files, or type it first in the source files and then evaluate in the repl?

2017-05-25T03:57:00.106Z

The later

2017-05-25T03:57:20.108125Z

If you wrap #(-> % val :product :name str/lower-case (str/replace " " "-")) in a function, you wonā€™t reuse it very often anyway because it tights to structure of the input map. I might group str/lower-case and (str/replace " " "-") together but not with the others

šŸ‘ 1
2017-05-25T03:59:22.122085Z

I believe you probably donā€™t want something like (defn access-name-in-map [m] (-> m val :product :name)) as well

2017-05-25T04:02:05.143138Z

I believe itā€™s same problem Rich said about Class and how you have to create a lot of duplicated methods to work with specificity of types

2017-05-25T04:10:31.201432Z

for me the tradeoff is still worth it when I look at:

(->> {1 {:id 1 :product {:name "Macbook Retina"}}} 
     (map (juxt key (comp #(str/replace % " " "-") str/lower-case :name :product val)))
     (into {}))
I have no idea what itā€™s doingā€¦ this I can read and understand:
(->> {1 {:id 1 :product {:name "Macbook Retina"}}} 
     (map product->name-in-param-case)
     (into {}))

lucasbradstreet 2017-05-25T04:24:03.292835Z

Yeah, I agree that that one is begging to be pulled out

lucasbradstreet 2017-05-25T04:24:23.294937Z

or at least use an anon fn in the form (fn [[k v]] ...)

lucasbradstreet 2017-05-25T04:24:51.298051Z

I love map juxt combined with into {}, but sometimes you can push it too far

lucasbradstreet 2017-05-25T04:27:32.315903Z

then again, I do kinda hate the #() anon fn form, so it could just be me

2017-05-25T04:29:52.331339Z

This is my personally opinion. For product->name-in-param-case, I have to jump to the source code to find out what it does. It might even have a surprise like side-effects inside. In many cases you need it, but not always. But for (comp to-slug :name :product val), I know it at a glance and fully understand what it does. And I believe itā€™s familiarizable. I think benefit of ability to see and understand more things in a single screen is not rated enough

2017-05-25T04:31:52.345732Z

However, I completely understand you all points. I definitely can see myself had the same opinion as you in the past. Just to give a different perspective.

jimmy 2017-05-25T04:41:46.411935Z

tap: in the case you mix -> and ->> you can use as->

2017-05-25T04:42:40.417906Z

Yeah, sure but probably not in an anonymous function, right?

lucasbradstreet 2017-05-25T04:43:29.423129Z

(comp to-slug :name :product val) is fine with me

lucasbradstreet 2017-05-25T04:43:42.424479Z

itā€™s once you start having to stick extra anonymous functions into the comp that I start thinking twice

2017-05-25T04:44:21.428694Z

yeah, thatā€™s fair

jimmy 2017-05-25T04:44:26.429187Z

true

lucasbradstreet 2017-05-25T04:44:26.429203Z

occasionally Iā€™ll use (comp (partial xx yy) ā€¦), I find that usually reads cleaner than additional anonymous functions

2017-05-25T05:04:47.567531Z

In that blog post, I also donā€™t fully agree with ā€œDonā€™t rely on implicit nil-to-false coercionā€. I think function like keep which operates on nil-to-false coercion is quite handy https://clojuredocs.org/clojure.core/keep

2017-05-25T05:16:02.641011Z

@tap: after reading Clean Code, I actually agreed with the author that I donā€™t have to understand all the details when Iā€™m reading through the code only if Iā€™m interested in the details of implementation, I would go and check that after applying this rule more and more, our codebase became much nicer to read for others it makes sense for you now to have all the details in one place, but it will be hard for others and your future yourself šŸ™‚ thatā€™s my opinion šŸ™‚

lucasbradstreet 2017-05-25T05:21:01.673512Z

Love keep

2017-05-25T05:34:06.760380Z

keep is nice, never used it

2017-05-25T05:56:03.910352Z

@andrut I really really like Clean Code. Itā€™s my first favorite programming book. And I do follow what the author said for years, religiously in some period of my career. It all comes down to finding a balance between verbosity and clarity. And I think Clojure gives us a possibility for different balance from static-typed OO language. Iā€™m not advocate for doing code golf here, but if we can get a short code with clarity, why not? (comp to-slug :name :product val) have almost the same number of character as product->name-in-param-case I donā€™t expect a person who donā€™t familiar with comp to understand this, but I believe anyone who familiar with it will understand this statement at a glance like me. I believe we should try to utilize more what clojure provides. If anyone donā€™t understand the statement, go play with it in your repl. I believe it wouldnā€™t take more than a few times, youā€™ll feel that itā€™s natural. I do have somewhat similar problem with assoc when I started using clojure. I came from a place where we use put or add to put thing into a collection. And maybe because Iā€™m not coming from native-English speaking country, the word ā€˜associationā€™ didnā€™t ring that meaning to me. Itā€™s not a word that I use often everyday. But I stick with it and one day it became natural. If I were to write code optimizing for myself who not familiar with assoc to read, Iā€™ll have to alias it to something like immutable-put

(def immutable-put assoc)
I believe everyone here would agree that I should not do that.

2017-05-25T05:58:17.926155Z

I agree (comp to-slug :name :product val) looks legit šŸ™‚

2017-05-25T05:58:30.927755Z

(juxt key (comp #(str/replace % " " "-") str/lower-case :name :product val)) doesnā€™t

2017-05-25T05:59:15.932959Z

what about (juxt key (comp to-slug :name :product val))?

2017-05-25T06:01:11.949Z

arguable, too much of mental overhead for me, but maybe Iā€™m stupid šŸ™‚

2017-05-25T06:06:16.986686Z

Nah, donā€™t go that way. I believe itā€™s just a familiarity. Again, totally understand you. Just trying to give an argument supporting my trade-off view. If we all agree with everything, we wonā€™t advance, right?

melindazheng 2017-05-25T06:41:22.260851Z

@tap ā€œIf we all agree with everything, we wonā€™t advanceā€ šŸ‘

šŸ‘ 2