Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

"The avoidance of side-effects is one of the key objectives of functional programming. Advocates of functional programming claim a number of benefits for the absence of side-effects including a greater ease of reading and reasoning about the code and an increased ability to execute parts of a computation in parallel."

You know I'm sympathetic to this line of thinking, but I wished he would have actually used this VM example to back up these statements.

Why is the version without mutable state better? That's not explained at all. I can think of some reasons why it would be worse -- e.g. more memory allocations. For this VM, its semantics are inherently serial, so the concurrency argument doesn't apply.



Well, the second version here is better for the following reasons:

- 9 less lines of code.

- Easier to see that it's correct. Partly because it's less lines, but partly because those lines are more meaningful and less bland. It would be hard to see a typo in the repetitive inner loop of the first version.

- Two obvious independent pieces of code instead of one big piece of code. That means if you're reading it, you know how to go about understanding it; understand each piece in turn. Somewhat trivial when there are 25 lines, but serious if there are 200 lines.

- Easier to test and debug. At a REPL, it's trivial to see what the stack is going to look like five hops into the functional version; you just apply the processing function five times. To do the same to the imperative version, you need to either write some debug logic into the middle of the function or set a breakpoint and hit 'continue' in your debugger while you count on your fingers.

Those reasons are typical consequences of writing your code as a collection of data and pure functions.

Also, the semantics are not completely inherently serial for most possible stacks. The sequence of operations forms a tree of computation, and the branches of the tree could be computed in parallel. If you actually wanted to do that (say, if the operations took a long time individually) then the way you would go about it is to construct the tree explicitly up front, take this functional version, replace fold with a version of fold that knows how to fold over trees in parallel, and fold it over the tree. Ta-da -- it would just work.


Another reason the second may be better:

- Wrap the stack program in a transaction and simply discard the results to roll back the transaction. In an imperative program it is error prone to roll back a complicated operation—the most innocent looking function might mutate external state.


Well technically F# has no purity handling, so it's just as possible for the most innocent-looking F# function to have side-effects as well.


Thanks for the warning. That sucks.


My read on this is not that he is claiming those things, but that he is examining those claims to see if they are true.

To be honest, not getting another breathless reiteration of the Functional Programming Dogma is a breath of fresh air. I actually like FP in the general sense, think interesting things are happening there, and am keeping an eye on it (as well as using it in selected places in my job where it makes sense, so I've actually put some cash down on the thing), but I'm really tired of people who have just barely learned enough FP to implement something of, say, this exact level of complexity making wild boasts about how good it is. I suppose it's a specific case of the general problem of seeing someone argue something you agree with, but badly.

This particular "integer stack VM implementation" is so trivial that you can't make arguments based on it. Both the imperative and functional implementations are too tiny to make pronouncements.


The most, imho, accessible discussion of this stuff is Dybvig's 3 implementations of scheme. The first 75 pages or so are just a great way of using a functional style of thinking to implement a functional VM. http://www.cs.unm.edu/~williams/cs491/three-imp.pdf

It's long and dense, but there's is a valuable point view there, and scheme sidesteps the whole strong typing set of issues. You get a complete, optimized scheme interepreter in , what?, maybe 150 lines of code? seminal paper for an autodidact.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: