←back to thread

296 points gyre007 | 1 comments | | HN request time: 0.214s | source
Show context
lewisjoe ◴[] No.21280702[source]
Richard Gabriel’s famous essay “Worse is better” (https://www.jwz.org/doc/worse-is-better.html) is an interesting perspective on why Lisp lost to C. In a way, the same arguments (simplicity vs consistency vs correctness vs completeness) can be made for why functional programming lost to OOP.

But those philosophical perspectives aside, personally I find my brain works very much like a Turing Machine, when dealing with complex problems. Apart from my code, even most of my todos are simple step-by-step instructions to achieve something. It’s easily understandable why like me, other non-math folks would prefer a Turing Machine over Lambda Calculus’ way of writing instructions.

This could be why OOP/Imperative was often preferred over FP.

replies(13): >>21280720 #>>21280760 #>>21280800 #>>21280835 #>>21280855 #>>21281061 #>>21281225 #>>21281281 #>>21281464 #>>21282667 #>>21283371 #>>21286296 #>>21288188 #
hyperpallium ◴[] No.21280855[source]
Even in maths, I find a solution in terms of the problem easier to understand than one in terms of the previous step.

Even when the recursive form is a more natural representation, like arithmetic sequences: start at s, increase by d with each step:

  a(0) = s, a(n) = a(n-1)+d

  a(n) = s + n*d
The analytical form seems simpler, neater, more "right" and more efficient to me - even though, if you want the whole sequence, the recursive form is more efficient (given tail-call optimisation).

I suspect I'm just not smart enough.

fp can be much shorter, and the execution model isn't actually hidden, just unfamiliar (and unintuitive and unnatural - for me). Consider: all suffixes of a list. In jq:

  while( length>0; .[1:] )
replies(3): >>21281308 #>>21283217 #>>21287870 #
jt2190 ◴[] No.21281308[source]
Lately I’ve been thinking that a lot of code style debates center around an explicit versus implicit axis. Imperative is more explicit, and, in one sense, easier to see what’s going on since it lays everything out step by step. On the other hand, those same steps are a mix of essential steps (that deal with the problem being solved) and accidental steps (that deal with computer and code in order to get the job done.)

It seems to me that OOP, Functional, and Relational programming models try to abstract away the accidental steps, but like all abstractions there are limitations.

I suspect that once familiar with one of these models, imperative seems awfully tedious, however now the code is more obscure to those not well versed in the paradigm, thus we have a trade off between ease of use for many and optimal for some.

replies(2): >>21281645 #>>21296080 #
1. hyperpallium ◴[] No.21296080[source]
Absolutely, explicit vs implicit is part of imperative vs. functional. And doing more with less information is elegant - and has a deeper significance in terms of Occam's Razor, that simplicity tends to closer to the truth, and therefore generalizes better. And, like pg's take, shorter code means less code to write, to read, to modify.

There can be leakage, when the given model is not perfectly accurate, and you need the true implementation details (this also happens for imperative code - it can be very helpful to have source of libraries) - in debugging, in performance, in working out how to do things.

But I feel a general issue is that it might not be a good fit for the human code processing system... Our interactions in the real world are more like imperative programming - not just familiarity, but how we evolved. This issue is similar to how quantum physics and relativity aren't a good match to the human physics system, which seems to be the mechanical/contact theory. To convert things to recursion is like working out an inductive proof - you can do it, but it is harder and more work than just getting it done in the first place.

A specific issue about this is that functional recursion is based on the previous step, whereas imperative code is usually based on the starting step. Like, build a new list at each recursion vs. indices into the input list. The latter is easier because it's always the same thing being indexed, instead of changing with each recursion.