I don't find this article well thought out. One, the writer presents OOP and FP as opposing paradigma's. While object oriented programming is orthogonal to functional programming. You can have a purely functional programming language with objects.
Two:
100% pure functional programing doesn’t work. Even 98%
pure functional programming doesn’t work
Doesn't work for what?
I think pure functional programming has its place, it is not just for everything you want to do. But object oriented programming is also not meant for every domain. It is like saying scalpels are stupid, because you can't build a house with them.
I think it all comes down to one thing: Shared mutable state. We can discuss what is functional and what is OOP, but in general functional programming does not mutate data in place. OOP does in general with encapsulated instantiated data in classes being operated on in that class.
However sometimes it is hard or impossible to avoid shared state even in functional approaches. So I suppose that is the 98% part. Things like databases, connection pools, files.
Since I have programmed in Clojure it has made me a better programmer even in OOP languages when I use them. I try to avoid self mutation and shared state as much as possible. I know there is a back and forth on what is the better way to program for a lot of things, but to me avoiding shared state is indisputably better for avoiding surprising bugs, and also for making concurrency much easier.
100% agree that shared mutable state should be minimized regardless of the paradigm used and further agree that it's generally not possible to totally eliminate it. I believe programming in a functional style helps on to adopt a mindset towards minimizing shared mutable state.
Also believe functional programming gets one to think in terms of function composition. Even in an OOP-heavy language like Java, one can find themselves developing complex operations as a composition of simpler, reusable operations. While Java may not have proper 1st class function nor solid syntax for working with functional interface, one can still think in terms of composable operations.
>Since I have programmed in Clojure it has made me a better programmer even in OOP languages when I use them
That is also my experience when visiting different paradigmas, they make you a better programmer, because they come with a different way of thinking.
>However sometimes it is hard or impossible to avoid shared state even in functional approaches. So I suppose that is the 98% part. Things like databases, connection pools, files.
True, true, most pure languages have an escape hatch. Or they pretend to you model the IO through some clever mathematical contraptions and then run it in the runtime during, you never guess it, runtime. But I feel that is just playing with words. Computers work with mutable state, so the 100% pure functional language doesn't even exist.
> does in general with encapsulated instantiated data in classes being operated on in that class.
I agree, but the general case is always a bit dull. There is no reason for a object oriented programming language to not have immutable objects. Every time you call a method that would normally mutate the object, you get a new one. And then perhaps with something like linear types you can make sure, you only used each object once, so you don't spray needless copies all over the place.
I think the axis he should be talking about is imperative programming and functional programming, those are opposites.
It implies that FP doesn't work in the real world without IO or without a runtime. When the author talks about "the messy parts that interact with the outside world" he's talking about the "Functional Core Imperative Shell" concept [1].
Of course lambda calculus doesn't work in the real world, the canonical purely functional language. It doesn't work, because it are just functions and those need input before they become useful. A function just sitting on paper doesn't compute anything.
However that is not entirely true, we can perhaps view analogue computers as purely functional computers, albeit one with continuous functions.
But besides such a weird example, we should not kid ourselves, most imperative languages these days also need a runtime. And if you take that a step further, assembly also needs a runtime. But that is I think not a honest argument, but still something to think about.
If we pursue this further down then we arrive at physical phenomena that do the computations. Are those imperative or functional? But now we are just playing around.
You can basically get the type of structured programming author is looking for with fully public structs in a functional language. And the pureness of functional paradigm is a bit of a strawman. Coming off of mostly C, C++, ruby, and python, I exclusively program in functional languages and have been for almost a decade now (wow!), and none of the fp langs (julia, elixir, erlang, react) that I have used have been "purely" functional. They all expose state (using different techniques - (bang functions, actors, actors, hooks) which are extremely well calibrated to the needs of their practioners. While that leads to a bit of fragmentation, it does also mean that the quality of code you release is better, because you're protected from making common mistakes that in my pre-FP experience, led to much teeth gnashing and hair pulling.
>I think pure functional programming has its place, it is not just for everything you want to do. But object oriented programming is also not meant for every domain. It is like saying scalpels are stupid, because you can't build a house with them.
You answered your own question. "It is not just for everything you want to do." He didn't say it was stupid. He said is is not for everything you want to do. You and the author are in agreement.
Well, it depends. I work on big clusters with lot of nodes. There you need to copy objects anyway. There is no shared state. I wouldn't like to use C there for example. In the language I work, objects are immutable and that makes it possible for a human to work with the cluster.
And of course there is state, I know that every node is plenty full of state, but that is not the point and it is hidden from me.
But if you writing device drivers, sure then it might not be ideal.
Immutable data structures and algorithms don't copy immutable state nearly as much as one might assume, and the vast majority of our field doesn't write software that is affected by the tiny performance differences between the underlying implementations of OOP Java versus functional Clojure, or perfectly optimized OOP JS versus naive functional Elm.
Sometimes its fine and sometimes its not but that is why 100% pure isn't feasible. I personally try take functional ideas into my OOP language as much as possible.
I think people care about performance without thinking about what exactly the bottleneck is. In some cases, it's the thing in front of the keyboard, in which case, you can do plenty of immutable state copying without worrying about it.
> I think people care about performance without thinking about what exactly the bottleneck is
Some of us are just permanently immersed in performance critical stuff. In gamedev, a single millisecond is a significant chunk of my per-frame budget and can stick out like a sore thumb in my profiling flamegraphs as an optimization opportunity / potential cause for hitching.
Pure functional code still has plenty of uses in this environment, but we've also got large chunks of our codebases dedicated to mutating external state (GPUs, Network IO, etc.) in horrifically performance sensitive ways.
> In gamedev, a single millisecond is a significant chunk of my per-frame budget and can stick out like a sore thumb in my profiling flamegraphs as an optimization opportunity / potential cause for hitching
Yes, but what is the relative portion of gamedevs among all devs? These people know who they are and they should absolutely obsess over performance. Everyone else should stop and think first.
Okay, okay. I'll make another carveout for certain classes of HPC. But even here, as the joke goes, HPC is the art of taking a CPU-bound task and turning it into an IO-bound task. I have heard of HPC people optimizing their numpy application to really run like the dickens on an HPC cluster, the scale their deploy from 1 to 40,000 nodes, and have the filesystem lock up for hours on what should be a 15 minute task due to the way python takes out r/w transactional locks on each and every one of its import statements.
> I'll make another carveout for certain classes of HPC.
And embedded. And anything RTOS. And kernel devs. Video encoders. And even some backend webdev stuff for scaling purpouses. And high performance logging systems. And ...
i am sorry. the larger population of devs care too!
bigger players have conditioned us to think that the status quo is normal. and this is working pretty well on those who haven't been around for a while.
those who have been around for a while are flabbergasted. dreams of seeing software loading right away and doing things of the past for them hasn't come true. note: things of the past (like loading up a text editor or an image!)
the excitement generated by unreal 5 proves that the status quo is not acceptable. we should be expecting much more.
> i am sorry. the larger population of devs care too!
Yeah. My point is, not that they shouldn't care but WHEN they should care. They should build their system, then measure the bottleneck. I would bet that 4 times out of 5 their initial intuitions are wrong.
>a single millisecond is a significant chunk of my per-frame budget
Interesting stuff, is that really a thing? Do you also have tools to measure this? I am genuinely interested, I like working under constraints, it makes programming more interesting. My main constraint is budget and total runtime of a job.
Yep this is really a thing. Game dev is an example of a realm where performance really matters and you need to tune that code to its target hardware, or some common denominator. Vtune is a pretty accessible tool if you want to profile your code on a Intel CPU. Also, rad game tools is a company that makes very useful tools for profiling.
I'm not in the gaming industry but the software I work on has a lot of visualization and physics simulations, so it's similar. It's definitely a different set of constraints, you deal with abstraction a lot less as well.
I'd highly recommend giving something like game dev a try, even if it's just as a side project. Handmadehero.org has great content. It's a breath of fresh air if you're coming from something like web development.
To maintain 30FPS you must finish a frame in 33ms (1000ms/30). To maintain 60FPS you must finish a frame in 16ms. Some of the VR literature I've read has recommended 90FPS or higher to combat nausea - 11ms. A millisecond could easily be 1/10th of your entire frame budget for the whole game's per-frame processing time, to say nothing of individual subsystems. At least we have multiple cores, but some stuff must run on the main thread...
> Also, rad game tools is a company that makes very useful tools for profiling.
arcin is of course referring to Telemetry[1] here, a wonderful tool for generating explicitly annotated flamegraphs that I've helped integrate into multiple codebases at different jobs. Engine-custom[2] tooling is also common, where you're seeing scopes measure in microseconds. There's a bunch of FOSS alternatives[3] of varying quality / functionality - nothing that's put Telemetry out of business for me yet though. "I'll write one myself for Rust someday!" I keep telling myself ;)
You guys have much cooler stuff to play with than I have for profiling things. Also better visualizations, but that is perhaps to be expected from the game industry.
>Some of the VR literature I've read has recommended 90FPS or higher to combat nausea - 11ms
That explains why VR is so computation heavy. Also curious what the mechanism is why you become nauseous under the 90fps. Perhaps the brain observes you are moving abruptly with lower frame rates, giving a constant sense of acceleration.
About telemetry. It feels weird that they are so flexible about their license, I am come from the corporate world, where licensing is set in stone. Is the game industry mostly informal?
>I'll write one myself for Rust someday
You do your game development in Rust? I have interest in Rust, because it has an interesting type system, but perhaps it would be nice to make a simple game in it to learn it and look how that goes.
> Also curious what the mechanism is why you become nauseous under the 90fps. Perhaps the brain observes you are moving abruptly with lower frame rates, giving a constant sense of acceleration.
I'm lucky enough to not suffer from the effects myself... supposedly Habituation can help, so perhaps I just read enough books in moving vehicles as a child?
> About telemetry. It feels weird that they are so flexible about their license, I am come from the corporate world, where licensing is set in stone. Is the game industry mostly informal?
It varies a good bit. Gamedev middleware shops are often small companies not burdened by large bureaucracies, dealing with high price, low volume sales - so they can afford a more high touch, personalized, and perhaps informal approach to sales. They also want to maximize the amount of devs trying their software - even if they don't use it for their current project or company, they might use it for the next, which is more sales - so they're quite happy to hand out evaluation licenses, or talk about missing features / platforms you might be interested in.
Those licenses are partially enforced by software, and for console versions, they might need to verify your lawyers have executed an appropriate NDA with Sony/Microsoft/Nintendo/??? before they even let you download those versions, however. Possibly via posting to shared, restricted access forums.
More standardized pricing systems are also common.
> You do your game development in Rust? I have interest in Rust, because it has an interesting type system, but perhaps it would be nice to make a simple game in it to learn it and look how that goes.
Just for my side projects so far - my professional gamedev work is generally C++ plus a dozen other languages that vary by company for scripting and supporting tools. There's a lot of interest in Rust, though - it's type system and borrow checker do a lot to catch the kinds of heisenbugs that plague large high-performance C++ codebases (which in turn lead to crunch, missed milestones, etc. depending on the company culture.) On smaller codebases, the borrow checker feels more like a nuisance than a help until you get quite used to it, but at this point I feel like I have gotten used to it (and perhaps become a better programmer in the pursuit).
In my next job search I'll definitely be keeping an eye out for the chance to play with Rust professionally...
>I'd highly recommend giving something like game dev a try, even if it's just as a side project. Handmadehero.org has great content. It's a breath of fresh air if you're coming from something like web development.
Thanks for the resource :) Going to have a look. I am not a web developer, I am very bad at it for whatever reason. I fled the web a long time ago for the big data landscape. I almost ended up creating physical simulations of boats, but I missed that boat somehow, still a bit sad about it.
> You can have a purely functional programming language with objects.
Yes, but those objects would have to be immutable. Much (probably most) OOP and procedural software works with mutable data structures, which are forbidden by pure FP.
Two:
Doesn't work for what?I think pure functional programming has its place, it is not just for everything you want to do. But object oriented programming is also not meant for every domain. It is like saying scalpels are stupid, because you can't build a house with them.