4 ms·
I completely disagree. And I'd go so far as to say that a lot of that criticism comes from a lack of familiarity in functional programming/Haskell compared to i
by lclarkmichalek 12y ago
I completely disagree. And I'd go so far as to say that a lot of that criticism comes from a lack of familiarity in functional programming/Haskell compared to imperative programming. The argument of a loop being more realistic is horrible imo, as both refer to performing processes, which are abstract concepts: my mind probably views these differently to yours, and most likely very differently to a lay person, who will never have had to consider the idea.
I gave a talk recently, and I briefly explained how to decode a protocol buffer varint: if the last bit of a byte is true, shift the first 7 bits and repeat the process on the next byte. Does that map better to
getVarInt :: G.Get Int
getVarInt = G.getWord8 >>= getVarInt'
where getVarInt' n
| testBit n 7 = do
m <- G.getWord8 >>= getVarInt'
return $ shiftL m 7 .|. clearBit (fromIntegral n) 7
| otherwise = return $ fromIntegral n
or
def read_varint(self):
run, value = 0, 0
while True:
bits = self.read(8)
value |= (bits & 0x7f) << run
run += 7
if not (bits >> 7) or run == 35:
break
return value
I'm perfectly happy saying it is equally well represented on both of them. I know I much prefer the first, but that's probably just because I prefer recursion to an explicit loop. From the sounds of it, you'd prefer the second, and I believe that's just because you prefer loops to recursion.
- cageface 12y agoIn my experience the vast majority of people find explicit loops easier to understand. Thinking in terms of a function that calls itself is a struggle for most people. FP advocates that really care about language adoption should be more willing to recognize that this is a hurdle and not wave it away as a personal preference, IMO.
- lclarkmichalek 12y agoIn my experience, the vast majority of people do not learn a functional language to the point where they are productive in it. My hypothesis is that the correlation between people who finding explicit loops easier to understand and people who do not learn functional languages to the point where they are productive is evidence of causation.
- taeric 12y agoThe problem is a possibly little more fundamental, though. Explaining a looping function to someone can be as easy as "think of how you do the dishes, you take one... repeat until there are no dishes/soap/water/room left." This is very close to how every repeating process is taught and understood by folks. You take something, and repeat until there is a specific condition. Compared with a recursive solution. Which is of a few forms. One being to take your problem, break it into a series of identical problems and constantly restart with the results of having run a previous problem. I grant that a recursive solution is not that much more difficult to phrase this way. "Take a dish, clean... start over unless there are no dishes/soap/whatever left." I just don't know if I have ever heard something stated this way.
- seanmcdirmid 12y agoIn my experience, people who are ideological about FP often claim that the vast majority of people do not just get FP, and their preferences are misguided and not natural. Yet, sequential and direct control flow are common in human language, we know how to tell or be told to do something N times. Recursive formulations are harder to explain, and most people don't learn math as easily as they do language.
- rapala 12y agoIt's all about precision. To tell someone how to do the dishes seems easy. But give the same instructions to someone who has never done dishes and you quickly see the problem. It goes the other way too. I dare you to try and explain a simple repeating algorithm in prose. No lists or numberings allowed. Simple recursions work exactly the same as the equivalent iterations. They branch on a condition, execute a step and repeat. How state is handled is the key difference. As Haskell has no concept of a variable, the only way to rebind a name is to recall a function. I was going to say that a professional in our field who has problems with recursion and the basics of discrete math should take a look in the mirror. But maybe we have managed to raise the abstractions high enough so that one can be productive without knowing the fundamentals of computing. I probably need to broaden my concept of a professional in our field.
- Tyr42 12y agoI don't understand where you have "run += 7" and break if run = 35 in the python code. Does the Python code have more error checking than the Haskell code?
- gamegoblin 12y agoThe Haskell code checks this implicitly with the use of the Get monad, I believe. In Python, you have to manually tell the code to not reach for bits that aren't there. In Haskell, the concept of a failure state being implicitly dealt with is used all over. Also, the reason the Python code is a `while True` with an explicit counter and check at the bottom is because Python lacks a do-while loop
- lclarkmichalek 12y agoHuh, yeah, didn't notice that implementation difference. In the Python code, the longest valid varint is 5 bytes (want the result to fit into int32 I guess?). In this case the bug is not strictly a problem as the Haskell code is used to read varints from trusted inputs only, whereas the Python is designed to read untrusted input. But good catch