
Miguel Mitrofanov
Maybe it's just me, but I think composition chain is MUCH easier to read.
I definitely agree. [Cited from "Learn You a Haskell for Great Good"]
oddSquareSum :: Integer oddSquareSum = sum . takeWhile (<10000) . filter odd . map (^2) $ [1..]
oddSquareSum :: Integer oddSquareSum = let oddSquares = filter odd $ map (^2) [1..] belowLimit = takeWhile (<10000) oddSquares in sum belowLimit
To me, the first one is very clear, and exposes the function as what it is: a neat, linear pipeline of standard function applications. You don't have to be a very seasoned programmer to quickly identify this structure, or the components involved. Introducing names means that I need to keep the temporary definitions in my head, and I think "takeWhile (<10000)" is as clear as it can get. And while a name can be misleading (belowLimit is a boolean, no?) or flat out wrong, the definition has its semantics¹. Another, perhaps graver issue, is that the names obscure the linearity of the function. I now need to check that the temporary defintions don't recurse or perform other tricks.² Named values are just like comments, which IMO also should be kept to a bare minimum. A bit tongue in cheek: If you need a name to understand what a function does, or a comment to understand how it does it, then your code is too complicated. -k (who still doesn't name all his functions 'foo') ¹ Which are perhaps not-so-defined. Thanks for bringing it up. ² There are plenty of point-free examples that overload my mind -- I wonder if this might be when you start to linearize non-linear structures, composing dots and combinators and whatnot? -- If I haven't seen further, it is by standing in the footprints of giants