>From my own experience I think the following is relevant: - functions are either specific to a context or abstract. Specific functions need to be understood in the context of their call site and the domain. Trying to make the name of the specific functions capture the entire context leads to noise. I would gently suggest that most of your functions are specific, particularly the ones motivated by extracting intent. They aren't and almost certainly can't be reusable so their call site is part of their context. If you do want the to be reusable then all that context caotured in the label works against you - again, the drive for reusability and the drive for "future proofing" often lead us astray. In the solution domain there is only one sensible interpretation of flipping vertically - there is a hint of trying to make the code completely unambiguous and self contained. This is also very similar to trying to make it idiot-proof. I don't think any of these are achievable. (Collective gasp whilst I out on my fireproof coat). The syntax of any programming just isn't expressive enough. Literate programming rocks, but that is because you aren't writing code, you are writing prose - FP programmers tend to be more familiar with the inbuilt catalogue of idiomatic FP solutions, and dare I say I have met many more "average" OO programmers than FP programmers :). This, coupled with the succinctness of Clojure means idiomatic Clojure already contains a bunch of context. You don't need to tell me what your code is doing because idiomatic Clojure code is inherently readable *once I grok idiomatic Clojure*. For me, I found myself writing that sort of code at the beginning because I was compensating for my lack of familiarity.
Nowadays, I tend to find it much more successful producing code that has a certain number of assumptions: - it will be maintained for far longer than it took to write (some of our apps are decades old) - readers will be competant wielders of the toolsets used - idiomatic code is strongly preferred, as are coding conventions - reader understands the problem domain and the solution domain Trying to write code that is somehow a training manual, a design document etc. Is a hiding to nothing. The best communication tool I have found is regular discussions with the relevant people. Corporate mindshare is best maintained through words not code. I said before, and I think I it needs repeating as you asked again, but no, I dont think FP is any less concerned with the WHY or the HOW etc. I do think it uses seperate tools to achieve the same goals. I would claim that my code still satisfies all of the excellent points rsised in the best practices literature, but Clojure doesn't require the same verbosity. As ever, this is only my opinion :). On 14 Dec 2014 07:34, "Philip Schwarz" <philip.johann.schw...@googlemail.com> wrote: > Hi Leif, > > if I compare your suggestion > > (let [top-right (create-top-right-quadrant-for letter) >> right (stack top-right >> (flip top-right)) >> diamond (beside (map reverse (drop-first-col right)) right)] >> (display diamond)) > > > with mine > > (let [top-right-quadrant (create-top-right-quadrant-for letter) > top-left-quadrant (drop-first-column-and-reverse-every-row-of > top-right-quadrant) > top-half-of-diamond (join-together-side-by-side top-left-quadrant > top-right-quadrant) > bottom-half-of-diamond (flip-bottom-up-and-drop-first-row-of > top-half-of-diamond) > diamond (put-one-on-top-of-the-other top-half-of-diamond > bottom-half-of-diamond)] > > yours is more inviting, and mine just looks like a barrage of verbiage. > > But with some judicious spacing and syntax highlighting, I think mine > regains IMHO its effectiveness > > (let [*top-right-quadrant **(**create-top-right-quadrant-for * > *letter**)* > *top-left-quadrant * *(* > *drop-first-column-and-reverse-every-row-of* *top-right-quadrant**)* > *top-half-of-diamond* *(**join-together-side-by-side* > *top-left-quadrant * > * > top-right-quadrant**)* > *bottom-half-of-diamond* *(* > *flip-bottom-up-and-drop-first-row-of* *top-half-of-diamond)* > *diamond* *(*put-one-on-top-of-the-other > *top-half-of-diamond* > > *bottom-half-of-diamond**)*] > even better if I adopt the 'beside' you suggested, and its 'above' > counterpart: > > (let [*top-right-quadrant **(**create-top-right-quadrant-for * > *letter**)* > *top-left-quadrant * *(* > *drop-first-column-and-reverse-every-row-of* *top-right-quadrant**)* > *top-half-of-diamond* *(**beside* *top-left-quadrant * > * top-right-quadrant**)* > *bottom-half-of-diamond* *(* > *flip-bottom-up-and-drop-first-row-of* *top-half-of-diamond)* > *diamond* *(*above *top-half-of-diamond* > *bottom-half-of-diamond**)*] > > Do you see the value of hiding the HOW at all? Imagine if this was > something more complicated, e.g. a financial application: wouldn't you be > thankful for being spared the detail of HOW things are implemented until > that time when you consider it useful to understand it? > > We talked elsewhere in this thread of separating intention from > implementation by using the Extract Method refactoring and implementation > patterns like Composed Method, Intention Revealing Method Name, Explaining > Message, etc. But the above code also highlights that other simple > technique we can use to separate WHAT from HOW: the Introduce Explaining > Variable refactoring (http://c2.com/cgi/wiki?IntroduceExplainingVariable > - AKA Extract Variable http://refactoring.com/catalog/extractVariable.html). > Instead of forcing the reader to deal with the whole of a non-trivial > expression which is all about the HOW, we can factor out one or more > sub-expressions and give them a name that says WHAT the expression(s) do. > In your 'let', you have two explaining variables, whereas I have four. > > Do you see the value of hiding the HOW in this way? > > Philip > > > On Tuesday, 9 December 2014 05:06:22 UTC, Leif wrote: >> >> Hi, Philip. >> >> I had the same urge as David--I tried it out, glossing over any formal >> rules. Here's what I came up with: >> https://gist.github.com/leifp/ae37c3b6f1b497f13f1e >> >> In truth, I think David's solution is more readable and maintainable. >> But I think "maintainability" is a pretty tricky concept: >> >> My code makes a seq of maps describing rows, and then turns them into >> strings at the end. This is probably more work to understand than David's >> solution. But is it less maintainable? Well, currently, the answer is >> "yes," but what if I need to output a diamond in several different >> formats? What if marketing wants each row to be a different color and >> font? I would start to favor my solution in that case. My point is that >> the difference between "maintainable" and "horrible" is evident, but the >> difference between "maintainable" and "easily maintainable" depends on >> predicting the future somewhat. >> >> I also favor a slightly less verbose style. A function is an >> abstraction, and you seem to be writing functions for very concrete steps. >> I think you have most of the correct abstractions for your solution method, >> you just need to consolidate the more concrete steps. Something like: >> >> flip-bottom-up -> flip (or vertical- and horizontal-flip) >> join-together-side-by-side -> beside >> put-one-on-top-of-the-other -> stack (or ontop, or ...) >> reverse-every-row -> (map reverse rows) ; very readable to clojure >> programmers >> >> (let [top-right (create-top-right-quadrant-for letter) >> right (stack top-right >> (flip top-right)) >> diamond (beside (map reverse (drop-first-col right)) right)] >> (display diamond)) >> >> The broad takeaway is: if I write a function I only use once, I usually >> just inline it. Unless of course I believe deep in my heart I'll have need >> of it somewhere else soon :). >> This is somewhat a matter of taste, and again, the requirements history >> usually determines what gets abstracted into functions, and history can be >> messy. :) >> >> Hope that helps, >> Leif >> >> On Saturday, December 6, 2014 5:48:02 AM UTC-5, Philip Schwarz wrote: >>> >>> Hello, >>> >>> can you please review my first solution to the diamond kata [1] and tear >>> it to bits: let me know all the ways in which YOU would improve the code. >>> >>> I am not so interested in a better algorithm for solving the kata. I am >>> learning Clojure and what I want to know is what YOU would do to make the >>> code more readable/understandable/maintainable, or just to make it >>> follow Clojure idioms and/or conventions that YOU find effective, or to >>> follow a coding style that YOU find more effective. >>> >>> Thanks, >>> >>> Philip >>> >>> [1] https://github.com/philipschwarz/diamond-problem-in-clojure >>> >> -- > 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 a topic in the > Google Groups "Clojure" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/clojure/zR5Ny7aoBM0/unsubscribe. > To unsubscribe from this group and all its topics, 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.