5 ms·
I had a chance to speak with John Backus when I worked at IBM where he invented functional programming with the goal of removing some of the spaghetti and incom
by dtagames 5y ago
I had a chance to speak with John Backus when I worked at IBM where he invented functional programming with the goal of removing some of the spaghetti and incomprehensibility of imperative and procedural code. It certainly was not an immediate hit!
Despite being an IBM Fellow (the company's highest rank with complete freedom to work on whatever you want), John was having trouble getting any traction for his ideas. I certainly didn't grok it at the time. I couldn't see the utility over the procedural PL/AS and imperative assembler we were already using to create the mainframe's higher-level language compilers.
I've since become a big believer in the functional style, sadly after John's passing. It's certainly not the solution for everything. Even the lambda calculus requires that you feed it a starting series of "magical" integers to work. But functional is a useful way of thinking about programming, especially for library functions.
I would say the key difference between the functional style and imperative/procedural is not the presence of recursion but the lack of state. A functional function cannot have any internal state store, nor rely on anyone else having one. In other words, all of its arguments and values must be fully defined by parameters. This is a super-critical concept in debugging because it helps bulletproof your function.
Having said that, no real working program can be fully bulletproofed with the functional style because we need to hold onto state in real programs. (Is the user logged in?, etc.) We cannot pass these values in every single time and have a practical program.
I think merging these concepts of functional when you can and state when you must is the easiest approach. Certainly there are many functions in every program which are functional in style in that they do not contain or rely on any state, and those are good jumping-off points for starting to understand the functional style.
- emodendroket 5y agoOf course a program without side effects is useless, but the idea is deferring those as much as possible, isn't it?
- dtagames 5y agoYes! JS and TS allow this kind of functional style which I try to adhere to. There must be state, of course, but as few functions as possible should rely on it and certainly no function should "reach" into anywhere else to get a value. Those things have to be passed-in. The change from AngularJS to Lit (or React), is an example of this kind of functional refactoring. AngularJS had two-way databinding (state!) and it attempted to pass that state upward when things changed. This made horrible spaghetti and impractical large apps. Lit and React are only top-down. Yes, each component has state but only at the top. It gets passed-in as a parameter to other things, but they can't change it in return. This is much more modular and debuggable.
- emodendroket 5y agoThe biggest downside with doing it in something like JS is you don't have the same under-the-hood optimizations. In functional languages it's not actually going to allocate a whole new array each time an immutable list is appended to, but that's exactly what will happen in JavaScript. But yes I agree, these concepts are showing up everywhere, even if you don't do "FP."
- pyrale 5y ago> In functional languages it's not actually going to allocate a whole new array each time an immutable list is appended to, but that's exactly what will happen in JavaScript. Efficiency depends on how your js runtime is optimized. Elm works fine, for instance.
- dtagames 5y agoAt the end of the day, software always exceeds the ability of the hardware to run it. That's the cyclical nature of our business. Just for myself, I'd rather write to the easiest software methodology and wait a bit for compilers/transpilers/interpreters, etc to be fast enough that it doesn't matter what I write. In other words, one can't really optimize for the top level (ease of use) and the bottom level (speed) at the same time. Turing demonstrated that there are only two differences between any computers that have ever existed: how fast they are, and how difficult they are to program.
- neolefty 5y agoYup, React is all functional these days, and pretty widespread. My team, for example, is "discovering" the benefits of functional approaches, and it's nice that it's a gentle slope.
- recursive 5y agoUse of state is still widespread. `useState` is a function in the javascript-specification sense, but not in the FP sense, since its only purpose is a side effect, not the return value. I don't think react can do anything useful if you use only FP constructs.
- carnitine 5y agoNo, a program without effects is useless. Side effects, i.e. some action done on the side while evaluating the program are not required. There are other ways to treat effects in programs, particularly as values.
- emodendroket 5y agoUnless you display them, save them, send them somewhere, etc, they’re useless. Therefore, a program without side effects is useless.
- carnitine 5y agoEffects, yes. Side effects are a particular form of effect. A pure functional language can compose an effectful value that is interpreted by a runtime, but no effect happens on the side as the program is evaluated.
- emodendroket 5y agoThat’s not really what side effects mean in programming: https://en.wikipedia.org/wiki/Side_effect_(computer_science) https://en.wikipedia.org/wiki/Side_effect_(computer_science) > In computer science, an operation, function or expression is said to have a side effect if it modifies some state variable value(s) outside its local environment, that is to say has an observable effect besides returning a value (the intended effect) to the invoker of the operation.
- ratww 5y agoGP is correct. There are zero side-effects inside a pure program. All the side-effects happen outside it, in a "runtime" (a better name IMO is "imperative shell") that exists totally separate from the program. The main() function of a pure program executes completely and terminates before any side effect has a chance to happen. I put quotes around runtime because it's not a runtime like an interpreter in dynamic languages, or a library that you can call from inside your pure program. This runtime just calls your main() function, which return a complex value (it's a chain of lambdas, to spoil it) that is interpreted by this runtime or "imperative shell". I understand this sounds unintuitive and might seem very confusing, but this is what makes useful pure programs possible. These couple presentations show how this type of boundary between imperative and functional code works with simpler type of program [1]. The only difference is that Haskell's "imperative shell" is lower-level than the presenter's. It only deals with IO, etc, whereas the presenter's imperative shell also has some domain code. [1] https://www.destroyallsoftware.com/talks/boundaries https://www.destroyallsoftware.com/talks/boundaries / https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell https://www.destroyallsoftware.com/screencasts/catalog/funct...