The Functional Programming Hiring Problem
blog.janissary.xyzThis is a problem that extends far beyond “esoteric language of choice”. It’s the challenge of being a nerd in a boring business world.
What attracts people to being a programmer? For some people it’s “looks like a reasonable job with good pay and conditions”. For others, it’s more “I love computers, programming, and abstract puzzles to solve”. This latter group (of which I am one), is more likely to provide both benefits and problems.
The benefit is they will generally be capable of greater innovation than the former group, but the downside is that they may just focus on interesting puzzles and ignore the needs of the (boring) business. Choosing an exotic language will greatly tilt the ratios towards this later group.
Most people in this later group can discipline themselves to focus on delivery, while remaining a great resource when truely challenging puzzles pop up. Most, but not all. Choosing a very esoteric language is pushing the curve far towards this tail, and the result will be many “brilliant, but useless to our business, people”.
Every small business needs a strong technical leader. I’m convinced of this. You need someone in charge that can stop the arguments, make people put down their toys, and remove people that cannot contribute for whatever reason. So this is my conclusion, it’s boring like so much of business. You need the right manager.
It’s a spectrum, it’s multidimensional and it changes over time though.
I love myself computers and probably more so earlier in my career than now, but I also like influencing people (often through code, with a focus less on algorithmic elegance but instead more on setting patterns, tooling, and APIs that influence how others build around them); and I also enjoy the challenge of aligning the pleasure of a juicy piece of elegant code against the pleasure of positive business outcomes. I think that makes me neither a “boring business person” nor a diehard code nerd, but somewhere at the intersection with attributes in other directions not captured by either stereotype.
That said, if you really are 100% motivated by abstract technical challenges, then maybe academia is more for you than industry is. Or working at the small slice of companies that truly make their bread and butter on cutting edge technical excellence and not, say, applying tried and true tools to some underserved niche.
I do find the “algorithm nerd” charisma also tends to intersect with having warped views of how the world operates and weak self-awareness, so maybe easier said than personally realized.
> That said, if you really are 100% motivated by abstract technical challenges, then maybe academia is more for you than industry is.
Of course. Such people very typically attempt to get a foothold in academia. The central reason why they nevertheless leave academia is because of the precarious job situation.
Hello! I'm just starting my career as a dev now and I am definitely more drawn to academia and research than to the business world. Could you point me to some resources where I can learn more about companies or projects that work researching CS/programming topics?
Thank you in advance.
If you are drawn to research, look at the affiliations of the authors of papers that you like. There are pockets like INRIA, Galois, Tarides, but it really depends on what research you are interested in.
> What attracts people to being a programmer? For some people it’s “looks like a reasonable job with good pay and conditions”. For others, it’s more “I love computers, programming, and abstract puzzles to solve”. This latter group (of which I am one), is more likely to provide both benefits and problems.
> The benefit is they will generally be capable of greater innovation than the former group, but the downside is that they may just focus on interesting puzzles and ignore the needs of the (boring) business.
I think the problem rather is that many "business people" have a deep hate against people who love to think about whether there is a deeper hidden mathematical structure behind the business problems. Just to be clear: there also exist some few business people who appreciate this, but the latter are typically "nerds" who mostly switched to business because it pays much better.
It's not my experience that the latter group of programmers ignores the business problems, they just rather have their own much less anti-intellectual way of approaching them.
It’s simpler. Business people hate paying people for any other reason than making more money.
Yep, the ‘nerd’ analysis of something that is very trivial is funny really. It’s money: most business peeps don’t give a crap about you or your skills: they pay the minimum they can to up the gains and that’s it. No more complex explanations are needed.
> who love to think about whether there is a deeper hidden mathematical structure behind the business problems.
Yup and lots of whom started with programming as a hobby, and could chase after any shiny thing they saw, or run off whenever on any side quest that interested them.
Nobody wants to pay you hundreds of thousands of dollars to navel gaze, or run off down whatever path you feel is mathematically satisfying. Do that on your own time. You're being paid hundreds of thousands dollars to deliver business value - so do that. Build mathematical towers on your own time.
It's like paying someone by the day to paint your house and they paint the Mona Lisa in white paint on white and take 3x as long because it's more artistically beautiful even if the end result is just an all white painted house.
"Don't you see the deeper hidden artistic structure!?"
> You're being paid hundreds of thousands dollars to deliver business value - so do that. Build mathematical towers on your own time.
A better understanding of the deep underlying structure behind the business problems is a step towards proving business value. This is exactly what I mean with a " much less anti-intellectual way of approaching [business problems]".
A better understanding of the deep underlying structure behind the business problems can be a step towards proving business value. Or it can be interesting to a small number of people, but completely useless.
Of course, the people to whom it is interesting think that the case they're interested in is almost certainly in the "providing business value" category. In their enthusiasm, they probably over-estimate the odds...
> "Don't you see the deeper hidden artistic structure!?"
This comes across as very snarky. The word used was "mathematical", not "artistic". Mathematics has proved invaluable in many domains of business.
> Mathematics has proved invaluable in many domains of business.
As has art.
Intriguing! Can you give some examples? And maybe contrast their preponderance to mathematical examples?
I can't plus this enough. I hired a unicorn business minded, brilliant, can solve any software engineering or UI/UX problem engineer who happened to have a predilection for functional programming.
I found out that unicorns are unicorns.
The problem, as posed, seems to be "when you hire $LANG devs, all they want to do is write $LANG, even when $LANG is poorly suited to solving the problem at hand".
To me, this doesn't seem to be a problem unique to functional programming languages. You'd have this problem when choosing any language outside the mainstream, I think.
From the article:
> Then, one thing leads to another, and you're knee deep in learning about homotopy type theory or continuations or whatever. Meanwhile, you're a week behind on that Jira ticket for issuing JSON Web Tokens because there's no actively maintained JWT libraries for Gooby.
You wouldn't have this problem in the first place if the language you chose -did- have an actively maintained JWT library.
Like, a company that chooses Haskell is a lot more likely to run into this problem than a company that chooses Clojure, due to the simple fact that Clojure can use Java libraries, whereas Haskell exists within its own isolated ecosystem. So, between the two, the likelihood is generally lower that you will, in the first place, run into a problem that Clojure can't easily solve.
So, in my mind, this essentially boils down to the same sort of risk/reward assessment you always need to make when choosing any language for any project.
As with everything, there’s some truth to that, but also C#’s json parsing libs are sub-par… and that’s really the least that a modern language should do well
I think Newtonsoft is quite ok, but the MS library lacks a lot.
Your information is very out of date. Microsoft long ago worked with the Newtonsoft.Json creator when introducing their native .NET replacement for Newtonsoft.Json. Performance in the new set of libraries is excellent as they rely heavily on the newer performance primitives like Utf8String, Span, etc.
I may indeed be outdated. Does Microsoft now support deserializing into dynamic for example?
You should never do that. Please do not, and I can't stress this enough, use `dynamic`.
If you need DOM-style JSON handling, please use JsonDocument and JsonNode instead: https://learn.microsoft.com/en-us/dotnet/standard/serializat...
There are plenty of cases where dynamic saves a ton of code.
No, it never does. There are better containers than dynamic, that do not have its performance drawbacks and have way better UX. The fact that this does not raise an eyebrow is a legitimate concern over the state of the codebase that uses it!
Are then even worse than Go's?
What is bad about encoding/json?
What do you think the following does?
The answer is "Moon:m2 Sun:"type Data struct { Moon string `json:"m"` Sun string `jsn:"s"` } func main() { var d Data err := json.Unmarshal([]byte(`{"m": "m1", "M": "m2", "Moon": "m3", "s": "s1"}`), &d) fmt.Printf("err=%v, data=%+v\n", err, d) }In list form:
1. Specifying unmarshaling shapes isn't checked by the compiler at all, typoing `json:"s"` as `jsn:"s"` should be a compiler error in any sane statically typed language, but in go, struct tags are untyped strings, it does not help you.
2. There are hidden unchangeable unmarsheling rules, like the fact that Moon=m2 is because unmarshaling is case insensitive, even when you specify an exact key name.
3. It's very slow, due to reflection.
4. The API also is not really type safe, things like `json.Unmarshal([]byte, d)` return an error, but should instead not compile because that's a type-error (non-pointer passed to function that requires a pointer).
5. It's slow. It requires a lot of allocation.
6. `json.RawMessage` is subtle and difficult to use
7. It can't stream, so it's very easy to open yourself up to DoS, or to run across json documents `encoding/json` simply cannot handle
I can't think of any other supposedly statically typed language, other than C, where the most commonly used json library integrates so poorly with the language's type system.
Rust's `serde` is what a good well-typed json library looks like.
Google really is the IBM of the past.
No matter how smart people are or how much money they get, they won’t create something good if the incentives for the individuals aren’t there. Everyone wants to prove that they are above the pack by instead implementing llms from scratch and boosting on Twitter, even though they just followed a guide for a week.
Im not sure how to fix it, but I think it starts with management that are strong willed, have pride, are aligned with the customers are able to make the developers proud in turn and dishing out low status tasks to everyone from time to time.
There is a version 2 being implemented to fix some of the known issues.
Thanks for the link. It looks like it might be a bit less painful?
It's still a pretty sharp disappointment to compare Go's json/encoding to Python's Pydantic or Rust's serde. One is all sharp edges, bad DX that permeates every use you make of them, and its only upside is that it provided as part of the stdlib. The other two are unobtrusive and just work.
I don't see why anyone should be a $LANG dev. All programming languages suck (there is this theoretical language that doesn't suck, but it isn't invented yet). Surely $LANG devs recognize that their language sucks, right?
And that's why we switch languages constantly. For some problems, some languages suck a little less.
I agree with your sentiment for the inverse reason.
Most programming languages are pretty neat. Learning is a joy. That's why language hops are fun and common.
But yes, few things make me cringe more than someone selling themselves short by introducing themselves as a $LANG dev
> And that's why we switch languages constantly
I only have one life and I prefer not to suffer too much; switching languages is not helping me at all in preventing that suffering.
Gooby doesn't suck though. (I'm not joking.)
> You wouldn't have this problem in the first place if the language you chose -did- have an actively maintained JWT library.
Actively maintained does not mean it’s good. We have to read and fork all libs we use (regulatory) so it won’t end up getting hacked etc, at least, less likely and a lot of ‘actively maintained libraries’ especially npms/pips are total garbage. We often spend less time just rolling ourselves than figuring out if this unreadable, overarchitected resume driven garbage even works.
Definitely the same story for PureScript. I rarely reach for Haskell now because I know I can leverage virtually any library off of NPM.
That approach also keeps you from hiring disgruntled devs.
It's hard to know from an interview what the quality of your Haskell code is.
It's probably relatively easy to find out in an interview that you had a lot of trouble with Clojure and are currently porting to Java.
> It's hard to know from an interview what the quality of your Haskell code is.
Please explain.
I work at a place that has ancestral Gooby code. It is truly horrific and an affront to whatever machine god (GPT-X?) may judge us in the future. The badness has literally nothing to do with the language. All the bad parts are due to the original team having reached for the most esoteric thing available at the time. I like playing with weird tech shit but there is a time and a place, and that place is not in prod for a startup.
They way overspent their strangeness budget[0] at every step of the stack. Even though I love (this) Gooby in general, in this case it has caused extreme damage to the organization.
I am still angry at the original devs for their choices because they basically poisoned the whole org against the language even though it would be useful for the org as a whole to adopt it in a non psychotic manner. It basically resulted in a reflexive ban for all Gooby in the future even when it might make sense.
[0] https://steveklabnik.com/writing/the-language-strangeness-bu...
I've personally seen this, it can be pure goddamn cancer.
The company hired a very smart charlatan and he convinced them to start a greenfield project in Haskell. Then they need to hire Haskell developers for this specific thing because everyone else only knows Java and Python. Nearly a year later they're barely getting started, but it's getting hyped like you couldn't believe. A lot of sprint planning time starts to become 'how do we start integrating [New thing]' because the Directors have been fluffing it so hard.
Anyway it never got used in prod. The development turned into a disaster and the original guy quit. The team got dismantled and the whole thing got memory-holed. Anyone in the org hearing the word "Haskell" would invariably just think about it lol
Not even sure these guys fit the standard mantle of language hyping charlatans. Most of the catastrophic choices were things you could do in any language. With the bonus of no meaningful comments and just committing to master so there's no PR comment history to help the future team's archeology project.
This is just a hiring problem, not related to functional programming. I agree with the basic premise of the article however: depending on the financial condition of the company, hiring people who are overly attached to or obsessed with a single technology probably isn't a good idea. But that's of course not exclusive to functional programming. Right now you will find plenty of people obsessed with Rust (not a functional language) who don't care about the business goals and only want to write Rust. A few years ago it was Go. Before that it was Node.js. A few more years ago it was Ruby on Rails.
This - I’ve had this same experience in both the FP, middle ground (Kotlin, Scala, etc.) and Rust space. It’s not FP, it’s that some engineers are interested in business goals and others are interested in conceptual goals. Those who are interested in conceptual goals gravitate towards conceptually interesting paradigms. Those who are interested in business goals gravitate towards business goals. It’s not mutually exclusive; I’ve met Scala and Rust obsessed engineers who also deliver; and Java engineers who can’t see past the next AbstractProxyFactory. But if I were forced to stereotype, new paradigms come with people who are more interested in the concepts than the goal (yes, I know FP isn’t new, blah blah, professionally speaking…)
While there’s some truth to “there are programmers obsessed with every language”, functional programming encourages a higher level of correctness, and this can lead to over-analysis and premature optimization if one is not careful. Yes, the additional correctness can be a real benefit, but only if the correctness is correct, and that really depends on the business. If the business comes back every week with “you know, actually we want…” you didn’t get a lot of benefits from the extra analysis.
Couple that with other challenges of running a niche stack in production and it can be quite a burden. Experienced, pragmatic developers will have techniques for managing this even in a functional language, but again, pragmatic may require compromise that doesn’t sit well with the purist.
I acknowledge that there are passionate users of most programming languages, but I also 100% agree that the FP crowd are something different. I feel like most other languages have some nuance at least; if you're writing transpilers or kernel modules then hell yes, Rust makes sense. If, however, you are trying to churn out a web-based store-front, maybe don't look towards Rust.
But with FP, it seems like it is always the answer. And it's even better if your Operating System can be immutable too. And your build scripts. And, even if it take 10 times as long to write, at least we will be confident that it's type safe at the end.
For the casual reader: Rust is one of the most functional of the not-totally-functional languages.
For the casual reader, if you think Rust is a casual way to play with functional programming, you will encounter the lifetimes booby trap.
It's almost always better to 'play' in a language that abstracts everything away except for the problem domain. Not like Rust, which introduces multiple complex language domains to learn before you can play wih your target domain.
This is why one of my favorite series of questions to pull out during an interview are:
What is your favorite programming language/library/technology?
What do you hate about it?
Anyone that jumps to answer the first but struggles to answer the second is likely not someone you want to hire.
This is the very first thing I do when picking up a new tech - language, framework, library, tool. After initial familiarization with the basics - Wikipedia/Readme-Intro, I would google "Why does X sucks", and try to avoid becoming overly enamored with it too quickly, and strive to maintain a level-headed perspective.
Ok. For anyone struggling with the second, the answers should be:
Lack of libraries.
Lack of good tools.
My favourite languages are C# and C++, and sometimes I interview developers to work with them. Saying these languages are lacking libraries or good tools is unreasonable.
True, but it's trivial to come up with things to dislike in C++ :-)
Great point on C++, but it’s harder for C#. The language and ecosystem are IMO pretty good.
I only hate that Microsoft stopped shipping modern .NET runtime with Windows. A few annoying things though, like the recent push towards AOT compilation (IMO strictly worse that JIT), and the lack of a good first-party cross platform GUI frameworks (for example Microsoft could compile d2d1.dll with DXVK, reimplement dwrite.dll API on top of FreeType / HarfBuzz, and copy-paste UWP).
What I dislike about C# is how much effort is needed to get a minimal environment. Rust and Python make simple code compilation quick and easy.
Let's assume I want to use a C# script .csx file. The CSX filetype seems to be Microsoft's flavor of attempting to "make it simple". I write a hello world. Now what do I do with the .csx?
I have no idea how to compile that with modern dot net.
It appears csi.exe would have been the answer, but now Roslyn seems to be the current best practice. No idea what to do though
I'm not sure where you are coming from in terms of difficulty of setting it up, it's just
If you want to use it as a scripting language, you do `dotnet tool install -g dotnet-script` and use it normally[0]. Keep in mind that C# is not designed for this, but it will work (at the cost of first uncached script launch costing extra - it is a compiled language after all, but that's a niche scenario anyway).- sudo apt install dotnet-sdk-8.0 / brew install dotnet-sdk - dotnet new console -o {folder} --aot - dotnet run -c Release - optionally dotnet publish -o .[0]: https://github.com/dotnet-script/dotnet-script?tab=readme-ov...
Thanks, I will look into the github repo. Although I think it's a bit confusing, since the steps you describe above lead to a requirement for the .net 8 runtime which leads to the following licensing information. It's not clear how to proceed with C# development as an open source language. I thought maybe it could be done by cloning Roslyn (MIT license) from github.
Do I need to accept the below licenses to develop a C# app? I'm not asking you specifically, just that I don't care to try and understand if I can even use the language without accepting any of the below, (anything not MIT or Apache)
License information for .NET on Windows
The Windows distribution of .NET contains files that are provided under multiple licenses. This information is provided to help you understand the license terms that apply to your use. By using any or all of these files you agree to their associated license terms.
The following binaries are licensed with the Windows SDK License:
api-ms-. (used by .NET runtime, .NET 6 and earlier) ucrtbase.dll (used by .NET runtime, .NET 6 and earlier) D3DCompiler_47_cor3.dll (used by WPF)
The following binaries are licensed with the .NET Library License
Microsoft.DiaSymReader.Native.{x86|amd64|arm|arm64}.dll (used by .NET runtime and SDK) PresentationNative_cor3.dll (used by WPF) wpfgfx_cor3.dll (used by WPF) The following binaries are licensed with the Microsoft Visual C++ Runtime Software License:
vcruntime140_cor3.dll (used by WPF)
All other binaries and files are licensed with the MIT license
This document is provided for informative purposes only, and is not itself a license.
I'm still as confused. Where do people even find those? Are you sure you are not intentionally misinterpreting information? Because it does seem so.
In any case: https://github.com/dotnet/dotnet/blob/main/LICENSE.TXT
I followed your instructions, ran dotnet build, and attempted to run the debug build .exe.
I got a message "You must install .NET to run this application."
So I followed the link[0] given as part of the CLI output which led to the .Net Runtime installer. Inside the installer it stated "By clicking install, you must agree to the following terms" and a link[1] was part of the terms I must agree to.
[0]https://aka.ms/dotnet-core-applaunch?missing_runtime=true&ar...
[1]https://github.com/dotnet/core/blob/main/license-information...
I would prefer not to accept non-MIT terms...
If text comprehension presents a significant challenge, you may want to consider other avenue of activity, over programming.
To those who are reading the thread, you are welcome to verify other claims made by the account I am responding to, which were proven by other participants false. This is a cheap trolling attempt and I think my response is the more polite way to share disappointment over this fact.
No need for personal attacks. I still stand by my opinion. Without a project template, you would be in the dark to set up a project. .sln files and .proj files are arcane and I might be dumb for not being able to create these by hand but I think most people would agree it is arcane hidden XML and a pain.
I need to reorganize the generated project template because it's not actually up to common standards of what a project directory should look like. As a newbie I would never know that I need to find David Fowler's gist[0] to have a project that makes sense.
Good luck trying to change the default .bin folder without aid from a third party's script or Visual Studio.
It's not obvious how to create a project settings JSON file. There are entire paid video workshops for this task alone. This kind of code should be pre-generated in the template.
This is all stuff that should be handled before a user even touches the environment.
It seems you're interested in proving your world view rather than finding (easily available) solutions to your problems (the whole argument was pure hypocrisy - you're asking about native dependencies that ship with OS, that isn't MIT, instead of using e.g. Linux, if that's what you care about). You did not even follow the initial easy steps to set up a project or did not look up basic CLI commands like dotnet new or dotnet sln to easily manage whatever you're working with (it's easier than Go and similar to Rust's cargo).
I have never seen a programmer struggle this much, failing to follow basic list of steps and ending up at the strange links from google, so my point in the previous reply continues to be relevant. Hell, an acquaintance of mine managed to get NativeAOT compilation working on the second try despite exotic NixOS setup and having zero experience with .NET beforehand.
And mind you, my first job was first level of customer support, so there were a fair share of users that misread the messages, and this case is like one of those bad ones. And, you know, the users who have a problem usually at least make an attempt to understand, as they are invested in solving it. But because you are invested in the opposite, no amount of explanation will help.
Note to readers: do not follow the structure at the link, it's outdated and refers to personal template preferred by David Fowler, you don't need all of that and it was also created during the days of .NET Core 1.
There are two main "project manifest"-like files that .NET uses: .csproj (or .fsproj and similar) to declare projects, and .sln to group multiple projects together. Those are managed with `dotnet new {templateName}` and `dotnet new sln` then `dotnet sln add/remove {path/to/project}`. Everything else is optional.
Not sure if this was a deliberate bait to demonstrate the problem, but Rust is a functional language in the modern sense (it has most of ML's features).
Hiring open source rockstars is problematic, so is hiring resume-driven trend-chasers.
But I think that author is missing at least one more category: senior engineers that worked in multiple programming languages over their career, who can see how design of Gooby and values of it's community create a better programming environment.
Indeed. Category 3 seems to be about developers who insist on using Gooby regardless of whether or not it’s a reasonable choice for solving the current problem. What about developers who simply have Gooby as one tool in their toolbox, know how to use it, and enjoy doing so when an appropriate opportunity arises?
I once wrote some Haskell professionally. It was a successor to a previous generation of the application that I had written in Python and maintained for several years. Using Haskell was my choice and it was made because some of Haskell’s strengths would address specific pain points learned from that experience. Meanwhile, everything else I wrote for that client was still being done in mainstream languages for mainstream reasons and there was never any suggestion that we would rewrite anything else in Haskell or adopt it by default for any new work, so I think this situation is clearly distinct from category 3 in the article.
At this point pretty much any language you want to pick for me is a couple weeks’ ramp up time. I couldn’t really care less.
What’s the right language? Probably the language you’re already using for the rest of your stuff so we can interface with the rest of the org efficiently.
Is it new? Grab whatever the industry standard is for your segment. Lots of libs, lots of mindshare, easy to hire, get it done.
I do get caught in HR filters a lot without a bunch of projects in gooby though.
> At this point pretty much any language you want to pick for me is a couple weeks’ ramp up time. I couldn’t really care less.
When you learn a programming language for a few weeks, the knowledge will be very superficial. Rather consider a few years of additional learning outside and in addition to the job to be realistic to get a decent understanding of the very encompassing and non-trivial details of the programming language, its lore, its culture and its often huge ecosystem.
> Rather consider a few years of additional learning outside and in addition to the job to be realistic to get a decent understanding of the very encompassing and non-trivial details of the programming language, its lore, its culture and its often huge ecosystem.
Not really, unless you're trying to extract the maximum performance from the compiler, or you're trying to publish your own libraries. You learn Java, C# is pretty close. You know LISP and Java, you can pickup Clojure really quick.
As for the ecosystem, what you need to learn depends on the problem, not on the solution. If you need to do JSON parsing, you take a few days to investigate the available libraries, write your own parser if none exists. That assumes you know what JSON is and what serializing data entails. These are universal problems that exists outside of the Knowing Language X scope.
I'd much prefer hiring someone who can build web applications than someone who knows express.js.
The ideas begin to repeat after a while. I’m a bit of a rolling stone. Most folks tend to specialize but I get bored easily.
> At this point pretty much any language you want to pick for me is a couple weeks’ ramp up time. I couldn’t really care less.
This is the right attitude
It’s just not that hard. Problem domains are hard. If you asked me to work in computer vision that’d be hard for me. Same for high frequency trading. Asking me to write this device driver in rust versus nasty old C, whatever man, bits is bits. I lie about my experience in different stacks solving the same old troubles all the time.
Languages are boring. Problem domains can be a lot of fun.
> The multi-armed bandit is a really interesting problem in mathematical optimization... This problem is so interesting, in fact, that during World War II the Allies proposed air dropping copies of the original paper over Germany. The end result, or so it was theorized, was that German scientists would be so fascinated and distracted by the problem that they would abandon the war effort and cripple any German military research projects in the process.
This is incredible
I heard something similar about the collatz conjecture that it was pushed/popularized by soviets to distract western development
It's so incredible you should not believe it.
Multi-armed bandits were introduced in the 50s, years after the end of World War 2.
Pulling from this published source[0]:
> As I said, the problem is a classic one; it was formulated during the war, and efforts to solve it so sapped the energies and minds of Allied analysts that the suggestion was made that the problem be dropped over Germany, as the ultimate instrument of intellectual sabotage.
[0]: https://academic.oup.com/jrsssb/article-pdf/41/2/164/4909740...
Wait, they actually tried nerd sniping[0]?!?
I would say "citation needed". Who said it? Where?
Yeah, by far the highlight of the article for me. In the very abstract, the idea to stop destruction by inspiring creativity is kinda beautiful
Sounds like an impractical (and ineffective) idea that was never implemented, so not actually all that incredible. Rather boring, inconsequential anecdote that adds nothing to the discussion.
Something can be inconsequential and yet still interesting/amusing
Is it amusing that someone suggested an impractical and ineffective idea once? There are billions more where that came from.
The classic story is how pg created a storefront in lisp that he sold to yahoo. Yahoo couldn't hire lisp programmers and rewrote it in another language (c++?) and it wasn't as good. But the decision still made sense from a business perspective.
And this article sadly shows why. Objectively, they aren't fair to "Goody engineers". Often, they mean opinionated engineers. Now opinionated engineers can be good and bad for profits - they work hard and point maybe good direction and maybe bad directions. But they make the company harder to sell and that objectively reduces the stock price and so it's bad from the "economic standpoint" even if it makes profits somewhat higher.
The problem is not with opinionated engineers. (Almost every engineer I know is opinionated; the ones who are not tend not to be very good.) The problem is with engineers who are excessively opinionated about the wrong things. Having opinions about the product is way more valuable than being obsessed with writing the umpteenth JSON parsing library in Gooby because the others aren’t built exactly the way you’d build it.
> Having opinions about the product is way more valuable
Be careful with this statement: many programmers value very different properties of the product than the typical customer.
Reminds me also of Figma converting all of their custom language stuff into Typescript, even though Typescript is slower.
Sometimes just using the language the majority of folks enjoy working in is fine.
You get programming astronauts in every language. There’s nothing special about Gooby or functional programmers that makes them deficient in the ways described. You could easily replace Gooby with Rust, Lisp, Python, C++, C#, Java, JS.
What makes the functional programming astronauts stand out is pure optics. If you’re tolerant of C++ templates or Python’s metaclasses you might view discussions on Profunctors to sound like gibberish. If you’re not someone who even uses those tools at all and avoid them out of principal it can sound like a plot for a hostile takeover. To an experienced Haskell programmer it’s likely to be fairly banal.
Which kind of blows this whole theory that Gooby programmers are the problem.
The real problem are those who seek to use a hammer regardless of what problem they’re trying to solve. I’m certain anyone whose been around for a while had encountered the “patterns astronaut,” who will view every problem as an opportunity to figure out how to apply as many GoF patterns as possible. These are the misguided souls we need to bring back into the fold.
In 2005, I needed to hire a Haskell dev with deep NLP expertise to replace a member of my startup team.
After a posting on the Haskell mailing list, zero responses came back.
We realized the world had about 3 people that matched all the requirements: one was the dev that needed to be replaced, the other one was a tenured professor of a U.S. university (Hi, Hal!), and there was one more, whom I don't remember but it may just as well have been Simon Peyton-Jones himself (only slightly exaggerating here).
Note the Haskel NLP mailing list - https://archives.haskell.org/projects-pipermail/nlp/ - did not exist then, it was formed only in 2009.
In the end, I forced a complete re-write in Java of our initial "rapidly prototyped" Haskell codebase at the time, and I often wonder what I would do nowadays, nearly 20 years later (Python is slow, has the commercial disadvantage of letting customers read off your secret sauce if code runs on their machines, but has a good dev pool to hire from, and definitely is both high-level enough as well as suitable regarding library support; ironically, Java is still a contender, despite the boilerplate Kotlin isn't getting the traction that Rust is getting against C, C++ has changed dramatically every 5 years in the 20 years since, and still ads complexity, which is all very scary, and Julia has a small talent pool, and isn't ready for prime time yet, certainly not regarding NLP libraries).
I know, since this is HN, people will say "LISP!", but I'm not sure; I always loved the aestetics of Scheme, but not the ergonomics - and my conjecture is there might be something about keywords that makes them superior cognitively for humans compared to just piles of nested parentheses.
EDIT: fixed a typo.
When you have one expert in something, you'll need to back them up or replace them in the future. You're job is to find three or four people that are decent at thing, and then put them all on expert tasks, as a team, so they grow into experts. This also frees up your expert to do that level or higher work.
I'm always surprised when I see this approach to hiring. I have a lot of Haskell in the codebase at my current company. It hrs never occured to me to try to hire from the "Haskell community" we always hire from our product community because tech is easier to teach than product.
> we always hire from our product community because tech is easier to teach than product.
Whether this is true depends a lot on the product and the tech that is used.
What product?
Pretty different if it's semiconductor engineers instead of the business school guys that would be covered by that sentence 99% of time.
> and my conjecture is there might be something about keywords that makes them superior cognitively for humans compared to just piles of nested parentheses.
It's the nature of the language and the VM that it runs in. The code is data and data is code. You can construct a list and then decide to evaluate it. Or the current code you're writing is actually data for another piece of code. It's a paradigm that really opens the computation mindset.
The VM looks like the common REPL you see in Python, but it's more powerful. It's more like a OS installation than a language interpreter. You can inspect anything, patch anything. When paired with an editor, that means you can only apply part of the code and then rerun part of the code. You can also try stuff and then formalize stuff down in code, no need to rerun the whole program.
For me, the parenthesis are the same as Python's whitespaces and colons. Or C-like language and their brackets and semicolons. Just syntax. After a while, you just don't notice them other than check that the expression is correct.
> You can inspect anything, patch anything. When paired with an editor, that means you can only apply part of the code and then rerun part of the code. You can also try stuff and then formalize stuff down in code, no need to rerun the whole program.
I’ve heard this a lot about Lisp. But doesn't this lead to greater cognitive complexity because every time you patch your running code, you have to keep in mind the state of the running program and mentally check whether your patch affects any part of that state?
A lot of people do data analysis this way in R/Python who aren’t programmers either by training or for a living, and it is not a practice that generally leads to bug-free outcomes. This has also mirrored my experience with Emacs which is a Lisp machine, maybe getting closer to Common Lisp’s programming environment.
Is this process of runtime modification fundamentally different in CL? What am I misunderstanding?
When you redefine a function in CL, every function that use this function is notified of the change and pickup the new version. And because it's functional and you're not supposed to modify the state outside your function, everything will keep churning.
The issue with emacs is the sheer number of variables. And the fact they're global. That leads you to do stuff you shouldn't do. But the principles are essentially the same. And in CL, you can snapshot the current state of your program to a file. Then restart later, instead of reloading the environment from the code.
A quick demo: https://youtu.be/jBBS4FeY7XM
Is this written from a different time line were TypeScript doesn't exist?
I have a long history of doing FP in a bunch of the traditional FP languages (Scheme/Haskell/etc). Ended up working at a young startup with equally young employees awhile back and was sort of surprised to see that the long heralded fantasy of cranky FP enthusiasts has, for better or worse, come true in Type Script.
I saw a generation of new programmers truly doing type-driven development and using a range of functional programming techniques without them even realizing that this was a big thing. Funnily enough they were terrified of anything resembling object oriented programming. If the word "class" appeared in the code base (their was some Python), they would quietly walk away.
What I saw was also incredible because these, largely junior, programmers were using types for exactly the thing old-Haskell people had hoped they would. Things would ship to prod lightning fast as all engineers had to do was make sure the types all lined up and the compiler was happy and they would send the PR off!
But then I saw the downside: these type-happy programmers almost never tested anything. I'm not talking about formal unit tests or integration tests, some of those existed. I mean these were programmers that had entirely lost (or maybe never had) the ability to play around with the code that they just wrote and make sure it worked. I kid you not, "print debugging" was viewed as some advanced technique to do in emergency situations. When bugs were introduced to prod I would ask "did this work when you ran it locally?" only to be met with quizzical stares. If it pasted the type check it was good to go.
It also had the negative consequence of inadvertently discouraging abstraction in favor of just adding more complexity to your existing types. Because refactoring code takes time and the entire point of the type check doing all your thinking is to ship fast.
All that said, I'd much rather work with that code base than one made by a similarly proficient team in say Ruby.
There are tons of skilled (and less skilled) functional programmers out there. The real problem is if you're looking for both highly competent programmers who also happened to be hung up on a particular niche language. I'm sure there are plenty of excellent "Gooby" engineers out there, but they likely choose jobs based on other factors than the language being used.
That's not a TypeScript issue. I've encountered the same problem of not testing things properly in other languages. There's a definite mindset amongst some programmers that if it compiles and the unit tests pass, then it must work. I think a lot of less experienced devs have read too many blog posts on PL theory/testing and don't realize how many bugs are just not going to get caught by such techniques. You really do have to see something work with your own eyes and hammer it for a while by hand to know it's of a decent quality.
The fear of OOP is a problem though. I've encountered some really bad TypeScript/JS codebases that were just piles of top level functions for everything. The meme that OOP is bad is really damaging.
What’s wrong with top-level functions (as opposed to methods)? Is there a meaningful difference between foo(bar) and bar.foo()?
Same reasons JS has modules that don't export everything, and for the same reason that React reinvented OOP under a different syntax with function components. Encapsulation, API design, runtimes and IDEs all work a lot better if the tools are aware of the link between the data and the code that's manipulating it.
To clarify: Are you saying they came to trust the compiler so much that they stopped doing local tests? If yes, this is an interesting point. When I toggle between Python and Java, I find the Java compiler has similar impact on me, as Python makes me so paranoid about runtime errors due to syntax.> But then I saw the downside: these type-happy programmers almost never tested anything.That's a really interesting data point about your experience with TypeScript. I'm going to have to file that away as something that I'm not sure what to do with right now, but also as an interesting thought to keep in mind going forwards.
The author brings up some good points here, but I would just make sure to build my business around trading obscure financial instruments in a clever way, so as to generate such an overwhelming amount of profit that we can singlehandedly rewrite and maintain everything in our stack from scratch.
I acknowledge, however, a lot of people never think to do this when starting their business, and consequently run into all sorts of this kind of trouble, sadly.
Is this a reference to one particular company/language?
Sounds a bit like Jane Street with OCaml
Language or any other technology you choose has the same problem.
Getting lost in the "tech $X is better for this than $Y" can easily become a distraction. Engineering is a form of applied science for money.
Since it's economically driven, the two most important things you as an engineer need to know are:
- who is paying for this?
- why?
Those two questions should underpin every single decision you make. If you lose sight of that, theres a huge chance you won't succeed.
I used to be more into functional programming but then I found other excuses to learn mathematics. I still think about how my imperative implementation can be turned into a functional one, or the other way around, but honestly the computer graphics programmers and machine learning engineers are doing cooler stuff. Even learning about category theory without needing to have an excuse to implement it makes it a lot more enjoyable.
One of brooks's papers (the guy that brooks's law is named after) is about how software developers would rather write the tools to solve the problem and then solve the problem itself.
A fair amount of this article is observing this problem persists 60 years later.
> how software developers would rather write the tools to solve the problem and then solve the problem itself.
That's because you know you'll be stuck with maintaining the solution. Nowadays, we have resume-driven people that just build stuff without any care as they know they're only here for two or three years.
In 2024 it is irresponsible to start that company off using gooby.
There’s plenty of mainstream programming languages that get the job done just fine without the hiring problems.
I’m 100% certain you don’t “need” gooby.
Hiring for gooby doesn’t scale, so unless your company’s goal is to stay small, don’t use gooby. And “the CTO likes it” isn’t good enough reason.
The original gooby loving CTO always leaves to spread more gooby to other companies and the owners of the company are left with a long term problem.
Just use the garden variety languages that there is a large talent pool for.
Do your gooby at home on your personal projects.
This is a good post with good points. What languages do you consider "garden variety" these days? For me: JavaScript/TypeScript, Java, C#, Python, Ruby. Unless you have very specific systems programming needs, I would avoid C++ and Rust, as once the project grows complex enough, you need to hire very skills (read: expensive) engineers.
Great post and very relatable. I too had my phase with a month of Haskell and then many more with Clojure. Even some other lisp exploration. It's a lot of fun, but I've since come to terms that from a career and business perspective I'm better off writing Python or Shell. (I'm a Infra/Devops guy, if it matters)
If you've already decided to use Gooby, a senior engineer who has already made significant contributions to successful Gooby projects seems like an ideal hire. If you haven't decided to use it, it's a waste of their talents, which they're letting you know before you hire them.
There's another side to this where one attempts to take the pragmatic or business value view (it' seems so obvious to) and is met with ostracism by those that are entrenched in a specific technology.
Here is the problem in the article: nearly every language is going to have the (3) people.
Hire people for embedded C and you will run into some some people to whom C programming and their side projects in it are more important than whatever you're trying to ship.
Substitute anything. Rust, C++, Ruby, Java, ...
And of course the resume stuffing (1) people are also a language-independent problem.
Certain languages probably won't have too many people in the (2) category (excited recent grads). But those are the good candidates in relation to (1) and (3), according to the Gooby analysis in the article.
I'm actually suffering from the opposite problem. CTO is a well known Gooby developer. But we wrote everything in C++ because "it will be easier to hire down the line", pulling in well known C++ libraries by various bigcos that actually don't compose together and make a royal mess of the codebase. We've missed every single deadline, and are light years behind where we should be.
Honestly we should have written it in C, but I'm too far down the totem pole to make that call
Now, the correct comment in this context; why not Rust?
I shudder to think of the levels of architecture astronaut that the CTO would rise to if we put rust in his hands
The blog post has some reference numbers embedded, but I cannot find the references below. (Did I miss something?) Specifically, the author hinted about a language and a company for #1. I guess this is Jane Street with OCaml? To be clear, you can make any insane language choice that you wish, so long as you pay so much money that no one will care. Exhibit A: Jane Street with OCaml
Ah, I think you're referencing the sidenotes. Sometimes the website doesn't render properly on mobile (I've tried getting click-to-expand working, but it's tricky), so try reading in desktop mode.
Regarding sidenote #1, I actually very deliberately did not mention the language or company ;) Here's the full text of the sidenote, if you're still unable to get it rendering:
> I'm not going to name the language itself, because this post would just turn into a flame war over that language specifically, and I definitely don't want to cast shade on any language/community in particular. I'm also kind of hoping that the most annoying people read this and think, "Ah, of course he's talking about that language over there! This criticism obviously doesn't apply to my perfect and favorite language!" Regardless, I feel that the thesis and content of this post applies pretty evenly to most functional programming languages.
That's the thing, though. Gooby is just a means to an end; the ultimate end goal of your company is to write software that is useful to people and makes money. For the zealots, however, Gooby is the end in and of itself.
So, where's the difference? One doesn't care about what they sell as longs it makes them money, the other as long they have fun.
An insightful post, this point resonated with me in particular…
However, I think that we all need to be a little more honest with ourselves as software engineers. […] Are you sure you don't use Gooby just because it's fun to write?
Why? I use raku every day just because it’s fun to write!
>Are you sure you aren’t just using Gooby because it is fun?
No. I don’t do anything (by choice) if it is not fun.
Exactly this. I'm indifferent to the most popular, ubiquitous, top-10-on-every-X-list trends. It's a pattern: something gains massive adoption only to fizzle out a few years later. XML, the one-size-fits-all OOP, all-in microservices, Silverlight, Flash, etc.
Usually, there are some good, pragmatic reasons why something gets selected, and it is always accompanied by trade-offs. The decision is not mine alone to make; we need buy-in from everyone on the team. If the choice turns out to be not very delightful or fun, it becomes obvious - replace it. My initial reaction to the question "Why are you using Gooby? I've never even heard about it..." is always "because it's fun"
And it is absolutely normal to become a team where everyone enjoys Gooby, and they'd try to hire like-minded people.
Just like functional programming itself, if you keep your hiring within some practical boundaries, you'll not go far wrong.
I've been on several sides of this issue. I've been using Haskell for around 16 years, and I currently work on a product that's written almost entirely in Haskell on the backend. I've worked in a variety of languages throughout my career, and I've taken plenty of jobs that involved no FP at all, jobs that involved a mix of languages, and some that were primarily Haskell.
I've certainly seen people in the Haskell teams I've worked on who fit the article's description of people who were there to write Haskell and didn't care about much else. It didn't go great, but they were a minority of the people I've worked with.
Importantly, I've also seen plenty of that kind of behavior in other teams using other tech stacks. I've worked with "Agile people" whose answer to every problem is pair programming. I've worked with people who only care about microservices, or their favorite frontend framework. I've worked with people who see more object orientation as the solution to every problem more often than I've seen people who want to apply FP to every problem.
A few of these people can be find to have on a medium or larger sized team- if the worst of their instincts are tempered they can be a great source of internal education and advocacy, and they can bring expertise that can help you deal with the inevitable problems and tradeoffs that come with any technical choice. You just need to be careful to, on balance, have a team of mostly product-minded people.
Product people aren't necessarily tech-stack agnostic. To use myself as an example, I really like functional programming and I think it's often a good technical choice. At the end of the day though, my job is a job and I'm there to build the best product I can to make my employer (and myself) money. I've turned down Haskell jobs because I didn't believe in the product or team, and taken jobs in less preferred tech stacks because I did. A lot of people can be both enthusiasts and pragmatists, you just need to look for them.
I think one of the biggest issues I have with the article is that it overlooks a significant source of hiring: product minded people who are open to, but not specifically enthusiastic about your tech stack. People don't need to be an FP enthusiast to work in a functional language. I've written a lot of Python and Go in my career, even though neither of them are my favorite language. By the same token, there are plenty of people who can work with Haskell, OCaml, or a lisp just fine with a bit of training even if FP isn't something they are going to devote themselves to. I've worked with a lot of people who do Haskell in their day job, but prefer to spend their free time using Rust.
None of this is to say that everyone should go out and use an FP language. I think the most important factor in picking a language is generally going to be picking something that your team likes and understands well. Most languages are good enough at most problems that individual preference is going to matter more than technical concerns. If Haskell or OCaml or Gooby is that preferred language for your team, I don't think you should avoid it.
4. They're SREs/PEs who mastered concepts in breadth of many languages and depth down the stack. Some us are even EEs who can do EDA work too for your custom hardware devices and write custom kernel modules.
Hire from group #2
Tldr: we want experts in our programming language but they charge a lot so it’s not good for our budget.
That's very strange conclusion. I think only person with limited exposure to tech hiring can produce that.
The way I see it, functional programming converts are often people who failed to properly grasp other, more challenging methodologies and decided that they need training wheels on their bikes. Though they won't frame it that way of course; they'll say that other methodologies lack the 'proper guardrails' which is telling...
I'm yet to meet an FP fanatic who actually properly understood OOP. Few seem to even understand the core principles of 'high cohesion, loose coupling' and fewer are even able translate that into a programming methodology.
My view of FP proponents is the opposite as the author claims. They're not rockstars who can master anything. More like the opposite; they're often people who are incapable of taking something complex and simplifying it. They're people who can't keep complexity under control and they need an external tool to do it for them.
> they're often people who are incapable of taking something complex and simplifying it.
Excuse me? Haven't a ton of things in recent years been simplified by borrowing ideas from FP? LINQ in C#, Flask route decorators in Python, React Hooks and Redux reducers, Rx in Angular, Kafka streams, and more?
> Few seem to even understand the core principles
They do understand specific pain points experienced outside of FP - side effects, mutable state, uncontrolled complexity. Many FP proponents are well-versed in OOP but choose FP for reasons like simpler state management, declarative syntax, and powerful concurrency models.
> They're people who can't keep complexity under control
> they're often people who are incapable of taking something complex and simplifying it.
FP langs specifically provide advantages for easier reasoning about code, deterministic functions, and improved reusability. Why would someone willingly want to try and take control of exploding complexity if they have already know better tools to manage it? Tools that they understand more thoroughly and that feel more "natural" to them, closely aligning with mathematical function theory. Math is already one of the best tools for describing a vast number of things in the entire universe. Why would anyone who understands math want to go study some other voodoo-doll piercing technique, even if it claims to be particularly effective at solving specific problems?
Interesting take and it feels familiar. I'm definitely in the "I need a tool to keep complexity under control" camp but I don't see it as a bad thing. Coming from a support and sysadmin/ops position seeing the same kind of problem every time makes you want to avoid the problem class. Of course it's often a fantasy. However I realized most problems I experienced were due to a general lack of understanding of the tools and concepts used. This was Java, Spring Framework, Aspect Oriented Programming and an ORM wrapper (MyBATIS) and 99% of my ops problems were due to the devs working around and against these concepts and tools with lots of bad code and so many NPE's that I still get nightmares. A skilled crew of veterans familiar with i.e. Spring, MyBATIS could have refactored this in a few months and most problems would be gone just using each tool how it was meant to be used. But we only added poorly understood layers upon poorly understood layers...
I understand everyone that goes into functional programming after realizing classes of problems don't exist there. I like guardrails. I learned to like immutable functional data structures after realizing 70% of time is Java serialization in the flame graph and I'd rather had the clojure way of solving these problems instead of the hidden magic. But properly learning all the mentioned tools and not abusing them would be enough.
> I'm yet to meet an FP fanatic who actually properly understood OOP.
You just haven't met one who has realized that monads in FP map roughly to objects in OOP yet. :) Both are used for the same broad things: encapsulating/hiding/controlling state and allowing state transformations to be sequenced.
I actually have great sympathy for the functional programmer: having decided that managing both kinds of complexity is mentally exhausting, the functional programmer opts to eliminate, as much as possible, the accidental complexity of willy-nilly side effects in order to better address the inherent complexity of the problem domain. A good programmer can write mostly referentially transparent code with controlled side effects in any language, but it takes more care and forethought to do so in, say, Java.
This is why I say Lisp is really for bad programmers. If you're a programming genius, you can apply the same principles used in Lisp all the time to Java or even C++ code... it's just more work. Work you may not even notice because that stuff comes natural to you. But if you're a mid programmer, much of the friction of working in Java or C++ goes away in Lisp and you feel relieved of a burden. Much more feels within your reach. (I happen to love Lisp, and prefer working in it to anything else if I can, so maybe I'm a bad programmer.)
This hasn’t been my experience. One attraction of functional programming style is that you tend to separate pure/declarative code from effects, one way or another, and then express each using familiar patterns of computation or interaction that are the essence of what you’re implementing. This often results in simpler and more explicit code, with exactly the kind of high cohesion and low coupling you’re advocating.
It is no coincidence that an expressive functional language like Haskell has concise, descriptive names for numerous common folding patterns over common data structures such as mapAccumWithKey¹ that let you express what you want to achieve in just a line or two of code with minimal boilerplate or ambiguity, where using a generic loop in a mainstream imperative language would take 3x that and need a little thought to recognise the pattern being used and make sure there wasn’t anything else happening that was tangled up in the same code.
¹ https://hackage.haskell.org/package/containers-0.7/docs/Data...
Do you have a great example of a code base that meets your ideals?
I think one of the problems is that we just don’t have people that we admire in programming compared to other areas like biology or literature.