The Worst Programming Language Ever
After trying out more than 40 different languages with varying results, I wanted to share the absolute worst language designs I have seen. Just my opinion though, don’t be mad 😄
I don’t want to judge a language based on what it is missing, rather on what it has, but implemented poorly.
For example, I do not like Go because it doesn’t have generics, but that doesn’t mean it’s inherently a bad language.
I could go on about esoteric languages like Brainfuck, as they lack basically everything, but there’s no point in that.
Weird operators
I really wonder who thought it was a good idea to change the fundamental operators.
In most languages if you want to compare two values, you either write a == b
or a != b
for negation.
In JavaScript you can also do a === b
, but at least that has a "rational" explanation due to type coercion.
In Visual Basic =
is either an assignment or an expression, it depends on where you write it.
Assignment: For index as Integer = 1 To 5 ...
Expression: If index = 5 Then ...
In LUA, you don’t write a != b
. You write a ~= b
The most overused joke on /r/ProgrammerHumor
Arrays that start at 1. I couldn’t not mention it right? I guess all programmers have an opinion on it.
Some of the languages that has this “feature”: Lua, Matlab, R, Julia, Fortran..
Inconsistent order of arguments
If you want to find the first element in an array matching a predicate, in Julia you would write: findfirst(predicate::Function, Array)
But Julia also has a function findfirst
that finds the first non-zero value with higher than i
index. Here the order of arguments are reversed and the array comes first: findfirst(Array, i)
.
If the order of arguments are inconsistent between functions, then you have to constantly look up the definition of the function and it slows you down.
Indentation that matters
The number one reason I don’t like python.
I wrote a lot of python in university due to course requirements, but I never started liking it.
From my experience significant indentation makes refactoring more difficult. Being able to just click “ALT+CTRL+L” and get automated formatting is awesome, but you can’t really do that if indentation matters. An accidental wrong indentation can put a variable in the wrong scope.. No thanks.
Niche functions laying around in global scope without a namespace
If you want to convert “abc” to uppercase. What do you do?
In an object oriented language it’s usually something like "abc".toUpperCase()
. In a lisp, probably (string/upcase "abc")
.
However, in Racket it is (string-upcase "abc")
. That's not a namespace, it's a global function and it's always available without imports.
Maybe that’s a bad example, since Racket uses “pretend” namespaces.
How about Perl? You would just write uc 'abc'
. The readability is through the roof!
Global functions makes it really difficult to know what function to use and you have to look at the docs all the time. If a function is bound to a namespace or object, it’s as easy as writing "abc".up
CTRL+SPACE and look for what’s available. Looking for what’s available in global scope is insanity, even worse if the function name is made up of two letters.
Inventing new function names
There are some functions that exist in almost every language. And they usually have the same name, or at least a very similar name. Which is a good thing. Using the same naming makes it easier for experienced programmers to learn the language.
How do you split
a string on a delimiter into an array in your favourite language? Probably something like a.split(",")
, right?
Swift does this all the time, they just invent new names for functions.
In earlier versions of Swift you split a string with a.componentsSeparatedByString(",")
. And then in Swift 5 they changed it to a.components(separatedBy: ",")
.
Just why? You’re only making it more difficult to learn your language.
And I’m not kidding when I say that swift used to have function called "".componentsSeparatedByCharactersInSet()
.
The name of the language
When I learn a new language, I often think about how I would solve it in a different language, and try to implement it in a similar way. Say I wanted to filter a collection in C#, I’d google “filter c sharp”, and I’d easily find the findAll
function.
However if I do the same with a language like Crystal, the google result would be totally irrelevant . If you create a new language please just pick a unique name, like “Clojure” or “Concurnas”. Unless your language becomes very popular, without a unique name to reference, it’s very difficult to search for relevant content.
Nothing is private and you can override anything
If the language has internal properties that it uses internally for multiple things, you should not be able to access them or override them. It can cause insane bugs.
Did you know that the spread operator in JS ...
depends on Array.prototype[Symbol.iterator]
?
If you want to mess with your team, just add this code anywhere in your project:
Array.prototype[Symbol.iterator] = function* () {
for (let i = 0; i < this.length; i++) {
if(i == 0 && this.length>1) yield this[1]
else yield this[i];
}
};
Now [...[1,2,3]]
will return [2,2,3]
.
That just shouldn’t be possible. Unless you’ve literally read the entire ECMA specification, you probably didn’t know that was a thing. How do you then even begin to debug the problem?
Has anonymous functions, but no proper shorthand
I refuse to use any language where you have to write a keyword to create an anonymous function.
Why implement support for anonymous functions, but not a proper shorthand? Even Java managed to do it.
Python does this. Why do I have to write the lambda
keyword? We already had languages with nice anonymous functions! You didn't have to do that!
An example of this atrocity in R:Filter(function(x) x > 5, a)
And Python:filter(lambda x: x > 5, a)
How it should be done!
In Swift:a.filter { $0 > 5}
Or Kotlin:a.filter { it > 5}
or a.filter { n -> n > 5}
Or JS:a.filter(e=> e > 5)
Begin End
What’s wrong with curly brackets? Why do you add begin
or do
and end
to you blocks? I especially do not understand it in Ruby. It’s a pretty nice and terse language, looks like the philosophy behind it was to write short cohesive functions, but then they add useless keywords at the end of each block. I really wonder what their reasoning was. Modern edgy language with a little sprinkle of Fortran.
if a > 5
puts "something”
end
End? End what? It just looks like clutter to me.
Unnecessary tokens
What’s the point in prefixing variables with $
? $
is not even easy to write, it just slows you down.
Perl does it. Declare a string? $a = '123’
. And then I want to declare an array, I have to write @a = (’1’, '2’, '2’)
. No thanks.
How do you get the length of an array/table in LUA? Just #arr
. Yep, for some reason, this symbol#
gets the length of a table.
PHP
My disappointment is immeasurable and my day is ruined.
Most languages have some quirks or reasons to why I didn’t like them, but PHP is so bad it needs its own category.
Almost everything in PHP is a global static function, and they’re all terribly inconsistent. Both in naming and order of arguments. Not to mention they use the dreaded $ prefix for variables.
Want to filter an array in PHP? You write array_filter
. Ok, for a global function that’s actually a pretty good name, but if you want to pass it a lambda you have to use the function keyword.
array_filter($a, function($n){return $n > 5;})
And yes, you need to write return
as well, and don't forget the semicolon. We just love verbosity.
Ok, I guess we could accept the function keyword.. Could we reference a function instead?
Uh, sure, just pass it a string.
function moreThan5($n){ return $n > 5; }
array_filter($a, "moreThan5")
If you wanted to refactor the name of moreThan5
, how do you do it? Does the IDE understand the difference between a string and a function reference?
Now, how do you think we map an array?
array_map($a, "moreThan5")
. Right?
Nope. It should be array_map("moreThan5", $a)
.
Yep, it’s array_reduce(array, fn)
and array_map(fn, array)
How do you split a string in php?
There’s the str_split
function, but it doesn't do what you think it does.
To split a string we write explode(",", $s)
Now, how do we compare two strings?
Easy. strcmp($s1, $s2)
.
You see what I mean? How do you know what function to use? They’re all in global scope and are all named randomly.
And they are random. Read about PHP history on wikipedia, quote:
The fact that PHP was not originally designed, but instead was developed organically has led to inconsistent naming of functions and inconsistent ordering of their parameters. In some cases, the function names were chosen to match the lower-level libraries which PHP was “wrapping”, while in some very early versions of PHP the length of the function names was used internally as a hash function, so names were chosen to improve the distribution of hash values.
Docs
So, with such inconsistencies, at least the docs are good right? Right..?
We want an $array.first(::predicate)
method, so we check the docs if it exists.
At last we find a method called array_search
that does what we want, let’s see the definition:
Ah. Yes. We are looking for the needle in a haystack. Very clever.. 🤦♂️ Please, your documentation should be as clear as possible. I can almost guarantee there have been some non-native english speakers going “WTF is a mixed needle?”.
PHP was the first language I learned properly. I used it at university all the time, and I’ve even been unfortunate enough to write PHP professionally. So lack of experience is not a problem when I say this:
PHP has to be the worst language ever made, and I feel truly sorry for anyone still using it. It’s the only language I use where I still have to look at the docs all the time.
Given that millions of people use PHP every day, it’s obviously not the worst language ever, but can I say “the worst language that ever took off”?
Don’t just take my word on it, there’s even a website dedicated to how bad PHP is: https://phpsadness.com