Why I Hate Programming Language Advocacy (2000)
perl.com
perl.com
Don't get me wrong, I wish programming language competition was less zero-sum than it is, but sticking our heads in the sand about it doesn't help.
Given generic language tooling innovation (lang server, llvm, ...) it's possible to launch a language with good tooling.
Given, also, the ability to piggyback on jvm/.net/cpython-vm (cf. julia)/c ffi/.. its also possible to launch with libraries.
I think today language popularity is a lot more about: (1) big name support; (2) killer app/library.
If you can't get (1), and you're in the lang. game, i'd be looking at a (2).
ie., solve some problem better than its being solved anywhere right now, in your language, in a way which naturally suits it. The opportunity cost (on using poorer solns) then forces adoption.
* Piggybacking: Scala/Spark, Typescript/Node, Exlir/OTP, ...
* Features: Rust/Saftey, Go/IO, ...
* Backers: Go/Google, Kotlin/Google, ... TS/Microsoft, ...
You're right that tooling is more important than the intrinsic properties of the language grammer & operational semantics...
However I dont think the stories of the above langs have been a story of tooling; in almost every case, quite the reverse.
The evolution of language can only be explained by considering context as well: natural languages are intrinsically tied to communities, tribes, culture, shared identities, shared morals and values, geography and so on and so on. In that regard, this evolution is extremely fluid. Billions of people know more then one language. Languages influence each other, as peoples and cultures meet. Sometimes, languages are adopted, like French was adopted by English elites after the Norman invasion, or Greek was the language of Roman elites.
Programming languages share many parallels with natural language. It's a fallacy to assume that programmers are homogeneous group of individuals with no discernible differences. On the contrary, being a programming is just part of one's identity. Most people come to programming because they are interested in solving particular challenges, or contributing to larger goals in specific problem domains or industries. The challenges faced by embedded system engineers in aviation are nowhere near the same as those faced by an frontend engineer specialized in using a particular content management system.
Moreover, many programmers don't reduce themselves to a single language. They might know the nooks and crannies of one or two languages in depth - much like a native speaker is innately wired to their mother tongue - but chances are they know a handful languages which are useful throughout their career and daily life, such as they identify parts of it with programming.
In that regard, I feel that the 'competition' between programming languages is largely perceived, instead of a real thing.
At worst, it leads people into "golden hammer" thinking about the tools they use. The "zero sum" thinking as you've pointed out, then reveals itself for what it is: a self-fulfilling prophecy, self inflicted by tool-centric thinking.
And that's exactly what the article is arguing against.
Can you substantiate this claim? They're not used in the same way, their learning patterns are different; the fact that we use the same word is coincidence more than anything IMO.
> At worst, it leads people into "golden hammer" thinking about the tools they use. The "zero sum" thinking as you've pointed out, then reveals itself for what it is: a self-fulfilling prophecy, self inflicted by tool-centric thinking.
Nonsense. The advantages of having good tooling and ecosystem are very real and concrete. If anything, the idea that particular programming languages are useful in particular problem domains is a lot more of an self-fulfilling prophecy - in my experience any halfway decent general-purpose programming language can be used in every domain if you actually try, usually the only reason to prefer a language with a good reputation in that domain is because there tend to be more libraries and so on, but that itself happens for purely circular reasons.
(If you really believe that programming languages are like natural languages, wouldn't you expect programmers to pick one and use it for everything?)
Their properties are essentially nothing alike. P-langs not having a semantics in anything other than a metaphorical sense.
Their extrinsic properties are similar insofar as they are inventions of human beings which have some socio-cultural dimension.
That's going to be an extremely limited experience. Most of the world's general-purpose languages have a heavy runtime. The runtime is expected to provide the running program with all manner of conveniences, but one very common item that you've probably imagined is just "universal" is an allocator so that you can... allocate memory. Nope. What programming language do you think the allocator is written in? Languages like C and Rust are designed with such a runtime as only an optional extra, so that you can in fact write the allocator in those languages.
"Heavy" by 1970 standards perhaps. When e.g. ML was first created, the newest and fanciest PCs had 512Kb of RAM. Nowadays if you wanted to buy a microcontroller with such a small amount of RAM you'd have to pay extra because you're asking for a lower-volume specialised part.
> What programming language do you think the allocator is written in?
Any language where someone actually bothered to actually try to write one - writing them in high-level languages has been done plenty of times with plenty of techniques (perhaps most elegantly in T by just carefully writing the allocator code such that it's not doing any allocations in the allocator itself). "Not actually needing to write a custom allocator" is also very easy in every domain if you actually try, IME.
The tautology you've inadvertently described there isn't actually an allocator. Isn't that fascinating? I can't tell if you were trying to be clever or if you just didn't see what you were doing.
What's actually going on is that T is sat on top of an entire operating system (often a Unix) which provides it with an allocator. It then uses garbage collection so that the lay user needn't worry about, like many high level languages.
But I disagree with lmm's larger point, and I will give my own example of it.
Here's an embedded system that controls the wing surfaces on a fighter aircraft. It has to adjust them every 1/40th of a second, or the wings break off (not an exaggeration). So a big part of the development process is proving that you always meet that timing. You do things like count the CPU cycles used by the code that the compiler generates.
Then someone says "let's use a garbage-collected language!" Worse, they may even suggest a language that automatically allocates. They might say that you can get garbage collectors and allocators that have guaranteed-worst-case timings. But even then, you have to count the allocations, multiply by the worst-case time of an allocation, and figure in the garbage collection time. And you're faced with a bunch of cynical embedded engineers, asking "Explain to me again how this makes our lives easier?" And you can't, because it doesn't.
You can write just about anything in just about any language. But software engineers aren't stupid, and they aren't sheep. The tools typically chosen for an area are usually better for doing actual work in that area.
Where did this "giant static array" come from? Seems like somebody allocated that to you and I think you already know where they got it. Keep going down the rabbit hole.
Somebody is at the bottom of the rabbit hole, and they are not using Java.
This is in fact an allocator, in the same sense that a C++ arena allocator is an allocator, and in the same sense that malloc is an allocator, and in the same sense that the OS's memory manager is an allocator. They're doing the same things - they're managing a block of memory, and returning sub-blocks of it when requested.
They're not using C or Rust either, they're writing some kind of machine-specific stub, probably in that machine's assembly language. Yes, a tiny minority of programmers do occasionally have to write the bit-banging stuff that connects hardware to a general-purpose programming language. But that's not a problem that having a different kind of general-purpose programming language helps with.
But that's what's so interesting at the bottom of the rabbit hole.
Unlike the languages you've mentioned, the ones used at the bottom of the rabbithole, such as C and Rust, actually provide a mechanism to do exactly that sort of bit-banging.
let x: u64;
unsafe {
asm!("mov {}, 5", out(reg) x);
}
Isn't that nice? All the surrounding code that isn't doing bit-banging still interoperates with this just fine, so you can do your bit-banging to talk to a memory controller and then... return a freshly allocated chunk of RAM to the rest of the high level code which has whizzy generic types and whatever.Because of Rust's safety rules we're obliged to explicitly flag that we know the compiler can't check our work. If this was serious work, we'd want to provide a comment for humans explaining why this is both necessary and safe, but in this toy example the answer is "No reason at all" so that's redundant.
In C, partly due to lack of name spacing, the mechanism is compiler-specific (of course today Rust is effectively wedded to LLVM so for now this is a difference without practical distinction). And there's no safety oversight, you're no more or less at risk when trying to make yet another linked list than when bit-banging. But otherwise it's very similar.
It's fine, but it's such a tiny fraction of what matters when producing a product that I wouldn't base my language choice on how good the language's support for that kind of thing is. I don't know exactly how e.g. Singularity or MirageOS do their bit-banging - for all I know they might even use a little bit of C or Rust to bridge the gap - but that bit-banging is such a miniscule proportion of what's important to an OS implementation (much less to an actual product built on that OS) that it shouldn't move the needle on language choice. I've never seen anyone put a genuine effort into running general-purpose language x on bare-metal hardware y and have it fail - it's always "we've tried nothing and we're all out of ideas".
That hasn't been my experience at all. Maybe 5% of the time there's actually a reason that makes sense. 95% of the time it's a case of we've always done it that way, one guy tried doing it a different way 20 years ago and it didn't work then so now we know better than to try different things.
If all other things were equal, yes. But the vast majority of people who sit in front of an editor are facing hard constraints such as scope, cost and time. The usefulness or suitability of any tool - including programming languages - is a function of those variables.
Is it possible to write a 3D engine in Perl? Yes. Not arguing with you there. Is it an exercise in masochism? Depends on where you're coming from, what your goals are and which constraints in terms of time and budget available you're facing.
The quantity of libraries which emerge around a language isn't that consequential. The number of libraries which are relevant to my particular problem or challenge is the metric that matters. Metacpan offers 250.000 Perl modules. But that masochistic video game developer won't be interested in the plethora of data manipulation packages and instead lament an acute shortage of decent and performant 3D rendering libraries.
Since then I have seen how this same mentality manifests itself on a grand scale on the net. Now description is advocacy.
We take on identity beliefs in so many areas of our lives (most commonly in religion and politics), and programming languages or text editor preferences are particularly notable areas of identity belief when it comes to programmers.
I've long given up participating in language or editor criticism because it's simply impossible to have a rational discussion about it. We used to have similar problems with RISC vs CISC discussions, but I think that has largely faded into history by now.
So anything that diminshes the value of X is seen as an attack of the valuation of the respective person skills.
It's natural and normal for young people, I think. It's easy to be entranced by some idea when you're in your teens and early twenties. Older programmers, if they stay active and not transition to management, early retirement, or get burned out and switch careers completely, tend not to be that dogmatic about the tools they use. I wonder what is the percentage of programmers below 30 years old in all active programmers?
On the other hand, getting dogmatic, cult-like even, is sometimes the only reasonable strategy for a language to survive. Languages that offer capabilities way beyond mainstream (which is not that hard...) often have a small, but very dedicated following. The people there have to believe their language is so much better than the others, because otherwise they'd have to admit that the amount of time and effort they pour into it is unreasonable. Such communities are allergic to posts saying that "another language also has this" or "you can do the same in language/tool X", and they demand a level of dedication which, for outsiders, is just creepy. But, without that, the whole project, the language and ecosystem, would simply die, and more often than not that would be a real loss for the programming world. It's hard to interact with such groups as a non-believer, but without them some of the great ideas of the past wouldn't be preserved, and some great new ideas wouldn't be implemented.
So, I think in some cases the fanboyism is a rational stance to take. In most cases, though, it's just immature expression of fascination, and then it indeed serves no real purpose, other than annoying more experienced devs.
This means the language you are familiar with will always looks more efficient and a better fit for any particular problem than a language you are not as familiar with. While tribalism and identity certainly plays a part in language wars, I believe the language advocacy is often genuine in the sense that the advocate really believe their preferred language is superior, and just want to help other people realize this. They genuinely don't understand why people would deliberately chose to use an obviously inferior programming language.
A example of this form of advocacy is the classic "Revenge of the Nerds" http://www.paulgraham.com/icad.html
> As an illustration of what I mean about the relative power of programming languages, consider the following problem. We want to write a function that generates accumulators-- a function that takes a number n, and returns a function that takes another number i and returns n incremented by i.
Note that the "problem" used to compare language power is not actually a problem. Rather it the solution a particular language would use to solve some problem. Unsurprisingly this particular language "turns out" to be the most powerful in the comparison. If we had chosen a different "problem" like writing a function which was statically guaranteed to return a list of integers, the winner would be different.
> Computer scientists collectively suffer from what I call the Whorfian syndrome1—the confusion of language with reality. [1]
And, on comparing languages [2] (paraphrased from "specifying" to "programming"):
> Comparisons between radically different formalisms tend to cause a great deal of confusion. Proponents of formalism A often claim that formalism B is inadequate because concepts that are fundamental to [programs] written with A cannot be expressed with B. Such arguments are misleading. The purpose of a formalism is not to express [programs] written in another formalism, but to [program] some aspects of some class of computer systems. [Programs] of the same system written with two different formalisms are likely to be formally incomparable… Arguments that compare formalisms directly, without considering how those formalisms are used to [program] actual systems, are useless.
[1]: http://lamport.azurewebsites.net/pubs/deroever-festschrift.p...
[2]: http://lamport.azurewebsites.net/pubs/lamport-verification.p...
Given this is the case I suspect, and here I admit that I'm extrapolating from a very limited dataset, that the root goes back to our early lives and education. There is some flaw in our education or thinking that fails to teach us to hear what somebody is actually saying versus what we want (or assume) they are saying. And that refusal to hear can, whether by accident or by design, come across as both stubborn and wilful, which only further serves to shut down fruitful conversation.
Sadly the issue now infects discussion on all manner of topics (both important and less so) and leads to heated debates and arguments that go nowhere. People literally become angry with eachother and fall out over... well, because they're not meaninfully communicating, they effectively fall out over nothing.
It's both ridiculous and profoundly depressing, but what I think it may indicate is a failure to mature in thinking. How widespread that failure is, is hard to say, but amongst people who use social media (for example) it appears to be at the very least a substantial minority (again, I haven't formally measured this so take the observation with a pinch of salt).
To someone who likes Walmart, the statement “I prefer Target to Walmart” triggers that part of human psychology, even though it shouldn’t.
You see it everywhere, in every subject, in any time period you choose to observe.
Edit: Charlie Munger understands this well and counteracts it by actively seeking to destroy his own opinions.
Maybe that binary view is one of the root causes, as being "wrong" is not really a thing in many areas. In fact this has roots in Aristotle's logic. Some years ago, general semantics ("the map is not the territory") tried to offer some push back on that binary view.
Humans do appear to prefer simplifications, with the binary point of view as a possible reflection of that, but we have had some success in evolving our tendencies through education.
PHP I hated but then we had someone brilliant with PHP come in and fix up the legacy mess we were dealing with. After that I grew rather fond of PHP. F# I really enjoy, but suspect that is because I have never used it under the pressure of a paid project.
Don't get attached to no language, no company, or no lover.
"that Linux guy" isn't impressive, but "Linux kernel maintainer" is
Besides, something like language and kernel design is computer science, not day-to-day software development that most of us do.
but who's coder?
in my opinion definitely Linux kernel maintainer will be better at topics oriented around OSes, low level, hardware, "system" programming, debugging
but I doubt he'll be also better at web development, fancy software engineering patterns/architectures (sagas, blabla), microservices, distributed apps, web security
I feel like those use different skills / kinds of knowledge.
Try using 'goto' around Java/C# people and you'll be considered as a witch, meanwhile I guess it's relatively not rare in Kernel development
Unless you actually need a web app. In which case the "Rails guy" will deliver in a couple of days something the kernel maintainer might struggle with for a couple of weeks.
Of course given 3-4 month the kernel maintainer could no doubt become a very proficient Rail developer if they felt incentivized to do so. Your average Rails developer probably won't be able to become a proficient kernel hacker in 3-4 month.
I once wrote a business-facing app in ExtJS. I played around with it, and I said, "ExtJS is cool, I am going to get good at it".
Six months of studying the dark corners of ExtJS and becoming really good at performance challenges and corner cases, ExtJS comes out with version 4, burning the bridges with new paradigms and making my "expertise" obsolete.
In general, stick to micro-frameworks. It's much harder to get burned in that world.
Companies that look for talented and true language-agnostic quick learners tone down their requirements for a specific technology stack, and sometimes don't even mention it.
Sometimes type checking is good, other times it gets in the way. It would be interesting if there were a way to compose a program with no typing, in order to quickly get to a MVP. Once done, you could then interact with the compiler/computer in a way to fully specify intent, and result with a fully typed codebase.
Being able to loosen up typing would likely have its uses as well.
If something like [JET.jl](https://github.com/aviatesk/JET.jl) become ubiquitous in Julia, one could add a function that pointed out all the places in the code where types are not fully inferred by the compiler.
It'll never be quite the same level of safety as a static language, however.
With dynamic typing, it is easy to make programs that work with types that are extremely difficult to describe and comprehend. I think that is what TypeScript has added so much advanced type theory level functionality: it is necessary to describe what people did with dynamically typed javascript. I imagine MyPy and company will have a similar trajectory for python. People did some really incredible things in these dynamic languages, things which are very difficult to describe formally.
Meanwhile, it seems to me at least part of the point of some statically typed languages is to force people to work with simpler type systems to solve their problems. Because those simpler types may be easier to understand even if they require more effort or more code to solve the same problem. I do think Go was far too adamant for far too long about not needing generics (also known as parametric polymorphism); seems sober minds clearly disagree about where to put the boundaries. To me it seems that statically typed languages embrace the notion of "Good enough, but not perfect." They provide enough expression to solve problems, but not enough expression to describe all solutions.
Immutability, strong types, no goto, no global state and the list goes on. These all avoid the complexity of too many possibilities.
There are plenty of examples where immutability is not the right fit (or even possible) or when static types are not helpful but just increase verbosity (and complexity). They might be good defaults (especially immutability if you can afford it) but not strictly the best way to reduce complexity in every circumstance.
Adamant is rather generous. Golang maintainers are overly defensive about serious deficiencies in an otherwise mediocre programming language. It is the worst tool for the job in almost any situation.
At the moment it is easier to write correct software in Python than it is to do it in Golang and in almost all cases correctness is more important than performance.
It seems to me like a sentence like this is exactly what the article was arguing against.
No, not really.
> Once done, you could then interact with the compiler/computer in a way to fully specify intent
Doesn't work that way. Once you went down the path of laziness and started to e.g., dumping data structures into untyped dictionaries or lists instead of properly specifying them, there is no going back without throwing out all the code and rewriting.
Similar to the way the precision of calculations in neural networks is shaved down for performance, but only as long as the output stays reasonable.
But also, when has typing ever gotten in the way? Actually having to think about the problem and the correctness of your program? It's somewhat amazing that correctness is so easily discarded. People just get stuck in a local minimum.
Correctness has little to do with it. Most type systems cannot express the actually important stuff, so you need to write defensive code anyway and make sure it works.
When you write in a dynamically typed language you are going to miss static typing sometimes and vice versa. The big advantage of static typing is performance and not necessarily correctness.
I disagree that performance is a big advantage. Perhaps there are certain optimisations that can be done if you have added more constraints? But that seems like an added benefit. I feel like there are a plethora of examples of type errors however. Obviously it doesn't rule out logical errors, but at least at the type level its "correct". You can even lift problems to just be type problems. For example only being able to construct inputs as something in the type system. Seems like that rules out a whole class of possible errors with parsing input.
I meant to say that some of many solutions can better, typically simpler, while being just as correct because you don't need to express it in static types.
> Obviously it doesn't rule out logical errors, but at least at the type level its "correct". You can even lift problems to just be type problems. For example only being able to construct inputs as something in the type system.
That is orthogonal to a type system though. If you take care of the invariants of a data-structure you are almost always going to need more than what most type systems can express.
In fact I would argue that type systems provide immediate documentation of very basic properties, which is often an advantage, but from my experience the errors it covers for you are rare, yet can be severe and confusing.
Again, having used both I'm not entirely happy with either. I prefer when static, or more generally developer-time-checks are opt-in and expressive, which seems to be a growing trend.
This is why Haskell and C++ do sometimes require types to be mentioned.
But what is not at all trivial is a lot of people exist who feel they have an 'edge' by knowing their language really well or feel threatened (or, indeed, exasperated) at having to learn a new language. I'm guessing this pool of people is also biased towards marginal programmers and people making money off advocacy.
It makes sense to me that advocacy would generally be of bad quality. The rewards for shepherding the programming community towards a more productive language are low and rare compared to the rewards of convincing people to do X where X is what the advocate is involved with already.
There needs to a bit of friction in the system or everyone is using discrete languages nobody else understands, even for irrational reasons.
And again, languages are also like cars... you usually want a simple enough car, that does the job.... if you go to ikea to buy a pack of curtains, you don't need a huge car, and a motorcyle is a best price/performance selection... if you can drive one. To translate this to languages, if you need to create something, use something that is able to do the job, and that you're actually capable of using to write the code for that job. Need to open a url, get an xml, parse it, and print a number from it to a terminal? Yes, optimized assembly will do it the fastest, perl/python/ruby will do it with the least code, but if you're only familiar with JS, even if it's slow, a a (node)js solution might still be best for you.
American politics has regressed on a scale of civilized to tribal. This is something we can all intuit and I think articles like this are going to become more common place. How do humans overcome base nature to become civilized? This is poorly understood. Religion wants to take all the credit. People like Stephen Pinker point to the Enlightenment being responsible and Enlightenment under attack today is civilization under attack. The fact our culture is coarsening into ever larger degrees of tribalism is disturbing. Computer science will not be able to stay out of the fray. Nor will any human endeavour.
If you are a bit experienced and/or educated, you can learn most languages fairly quickly. I'm fairly confident that most programmers will become reasonably productive with using a new language in under a month.
The issue is however that many of us don't want to be just "reasonably productive". We are nerds who really love what we do and take pride in our craft. So we want to dive deeper and deeper, reach competency and expertise and increase the fun we have continuously.
This part of continuous learning and refinement is rewarding but also really hard. A particular language can get in the way of that or help us to become better in some dimension of expertise. There is a mindset behind a language that might fit ours like a glove, it just flows more naturally.
But this emotional investment can sometimes hinder us in the long run, when we invest so much time and effort into something we don't like to hear that our choice was arbitrary or even bad in some way or another.
The antidote do that is to keep learning new languages and technologies at a reasonable pace. Suddenly the emotional attachment fades.