The other thing to watch out for when naming intermediate results is that you 
don’t hold onto the head of large sequences. It’s not a problem with these book 
examples but can be a problem in large scale programming.

 

Overall tho’, the readability of these different forms is very subjective. I 
personally do not like the #(my-fn %) form – I find the added “punctuation” to 
be noisy in comparison to (partial my-fn) – and we have a ‘flip’ function in 
our “utility” library to handle the first-argument-omitted case where partial 
is not suitable so we don’t need #(my-fn % :b :c) either. I prefer -> / ->> 
over composition of (curried) functions from a readability p.o.v. but I know 
other folks who prefer ‘comp’.

 

Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

 

On 11/3/16, 11:48 AM, "Leon Grapenthin" <clojure@googlegroups.com on behalf of 
grapenthinl...@gmail.com> wrote:

 

This style is only good if you do damn good naming on your "explaining 
variables". So while more names can really improve readability, bad names do 
the opposite by adding confusion and misdirection. This pattern enforces naming 
for every step. Good names are difficult, so I can only recommend to not use 
this style as a "silver bullet" or default. If you don't have time for the 
names in the first place, prefer threading macros, which still provide for 
great readability and can be edited with less typing overhead.

 

Note that you could have used the same names as right hand comments in the 
threading macro which IMO is the best of both worlds.

 

Regarding this discussion in general, I find #(my-fn %) to be preferable over 
(partial my-fn) in most cases. My understanding is that partial was introduced 
to the language before the terse lambda #/% syntax and is mostly superseded by 
it. 

 

In summary comp and partial are specifically useful if you transform functions 
algorithmically! If you just need to chain a few things while typing, #(... %) 
syntax and the arrow macro are most intuitive to write and read.


On Monday, October 31, 2016 at 3:50:08 AM UTC+1, Mikera wrote:

On Thursday, 27 October 2016 22:56:42 UTC+8, JHacks wrote:

I have some confusion about how the function `comp` works, especially as

compared to the threading macro `->>`.

 

>From the book *Clojure Programming* (pages 70-71 of Chapter 2: Functional

Programming), the following two functions are described as functionally

equivalent:

 

    (def camel->keyword

      (comp keyword

            str/join

            (partial interpose \-)

            (partial map str/lower-case)

            #(str/split % #"(?<=[a-z])(?=[A-Z])")))

 

    (defn camel->keyword*

      [s]

      (->> (str/split s #"(?<=[a-z])(?=[A-Z])")

           (map str/lower-case)

           (interpose \-)

           str/join

           keyword))

 

Why does the first function, `camel->keyword`, need to use `partial` with the

`map` and `interpose` functions? The second function, `camel->keyword*`, does

not need to use `partial`.

 

I actually prefer the following style to both of the above:

 

(defn camel->keyword*

         [s]

         (let [words (str/split s #"(?<=[a-z])(?=[A-Z])")

               lc-words (map str/lower-case words)

               joined-words (str/join "-" lc-words)]

           (keyword joined-words))) 

 

Reasons:

- Your intermediate values are explicitly named, which helps to make the code 
self-describing

- It is (marginally) more performant than the composed function case (I think 
exactly matches the threading macro)

- You can use the intermediate values in more than one of the following steps 
if needed, which can make refactoring / adding new features easier

- The ordering is (to me) more logical as it describes the stages of the 
transformation in the order they are performed.

- It is less "Clever". Clever code is generally bad for maintenance and future 
understanding. Both functional composition and the code-transformation effects 
of the threading macro represent conceptual overhead that you don't need to pay 
(in this case).

 

 

 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to