Beautiful code — The Manifesto
bestinclass.dk
bestinclass.dk
"I’ve received about 6 comments from C# developers all giving me their take on a better version of the liquid-value code above. A couple of them using Linq, which simplifies the code substantially. I’ve taken a drastic step in deleting all those comments — sorry guys!!"
sigh OK, clearly this guy is not worth attempting to have intelligent discourse with. What good are comments if you just delete those from anyone who disagrees with you?
Here the full quote: "Hi all — I’m serving up the first comment!
I’ve received about 6 comments from C# developers all giving me their take on a better version of the liquid-value code above. A couple of them using Linq, which simplifies the code substantially. I’ve taken a drastic step in deleting all those comments — sorry guys!!
Not because they didn’t present valid points, but because they entirely missed the point — I tried to spell it out with the K example — We’re discussing principles here, not code examples. I have no doubt that my rusty C# can be written in a more idiomatic sense, using better libraries etc. But thats much beside the point. The point is, that while the language so freely permits and even encourages me to code that way — I will end up seeing that type of code in my systems. If I had the privilege of hiring a team of superior geniuses and unspeakable coding skills, then sure, they might consistently produce rock solid functional code even in C# — but that’s not a real world scenario.
So lets stick with the principles. And if anybody does provide examples, please connect them with something discussed in the post. That makes for a better discussion than just swapping code.
Thanks to all for taking the time, sorry for being so harsh /Lau"
Using Clojure doesn't enable you to magically write perfect code. You posted well written Clojure and poorly written C#. You can write poor code in any language.
If you wished to remain on the topic of imperative vs functional, you should have avoided phrases like "using C# as the tool has added a huge degree of ceremony". You made a direct attack on the language, not on the coding style. You also make significant mention of the number of lines of code, but it seems as though you have intentionally included boilerplate to make your point. Being misleading and deleting comments are not ways to make an effective case for your cause.
EDIT: Oh, and on the actual subject of functional style. I still much prefer the C# approach as it reads in order you perscribed:
1) calculate liquid value of each item
2) filter candidates
3) accumulate value
(from asset in assets
let liquidValue = GetLiquidValue(asset) // 1
where DoubleMargin(asset, liquidValue) // 2
select liquidValue).Sum() // 3
Compared to the Clojure which reads: (reduce (sum-field :productioncost) 0 ; 3
(filter doubleMargin? ; 2
(map attach-liquid-value assets))) ; 1
or the Python which reads: sum(liquid_value # 3
for liquid_value, asset in assets
(get_liquid_value(asset), asset # 1
for asset in assets)
if double_margin(asset, liquid_value)) # 2Writing rock-solid functional code in C# is not nearly as hard or as strange as you seem to think. If it isn't a real-world scenario for you, that's just because you aren't interacting with the right C# developers. For starters, you could listen to the 6 comments (six? and you still say that it's not real world?) that were posted.
(reduce #(+ %1 (:productioncost %2)) 0
(filter #(> (:liquidvalue %) (* 2 (:productioncost %)))
(map #(assoc % :liquidvalue (* (:sdfactor %) (:productioncost %))) assets)))
vs. (from asset in assets
let liquidValue = asset.SDFactor * asset.ProductionCost
where liquidValue > asset.ProductionCost * 2
select liquidValue).Sum()
I'd prefer that C# _3_ code any day of the week.speaking of functional, i'm new to Haskell, but wouldn't it just be
f x = sum [v | (y,z) <- x, let v = y*z, v >= z*2]
assuming the argument is a list of tuples in the form (SDFactor, productionCost)you could also foldl if you don't trust the compiler to optimize the extra list iteration away.
i didn't really like the article. the tone was really grating. probably look elsewhere if you want some inspiration on functional programming style
(reduce +
(for [{:keys [productioncost sdfactor]} assets
:let [liquidvalue (* productioncost sdfactor)]
:when (> liquidvalue (* productioncost 2))]
productioncost)) (reduce (sum-field :productioncost) 0
(filter doubleMargin?
(map attach-liquid-value assets)))I compared a C# 3 expression to a Clojure expression.
And that bit of Clojure that you quoted uses helper functions which are not defined. The C# version of that is:
(from asset in assets
let liquidValue = GetLiquidValue(asset)
where DoubleMargin(asset, liquidValue)
select liquidValue).Sum()
Clojure is a great language, but this article unfairly bashes C#, which is also a great language.There is a place for mutation (certain algorithms absolutely require it), in spite of the obvious advantages of immutable+functional programming.
Not PHP, but C:
int x = 6;
I'm pretty confident about that one. A lot of those 1k lines of code will be "stating the obvious". I don't think it's fair to imply that the probability of a fault in a line of C code is anywhere near the probability of a fault in a line of Clojure.I doooo like Clojure though :)
(+ 1 1)
Done. Clojure's awesome, right? No errors. That rocks, huh?
No. Even that line has the potential for errors:
1. You could have a typo (int z = 6; int x = 7;)
2. You could have misunderstood the requirements (it should actually be float x = 6.5)
The only possibility you excluded with this trivially simple line is: 3. An error in how you used your own tools (easier to imagine if the line involved pointers).
Part of the difficulty of debugging is, you don't know which lines have errors in them. If you have 1000 lines, you potentially have to review them all to find the bug. If those lines are poorly compartmentalised, so that you can't heuristically find your way to the likely location of the bug, that is doubly the case. Conversely, if you only have 20 lines of code, then you only have 20 lines to read before you've definitely seen the line with the bug (whether you recognise it is another matter, which has more to do with experience, capability, and the clarity of the code).Intention-revealing code does tend to be much, much clearer, though. (although I'll grant you it's possible to obfuscate code with malevolent intent).