Clicky

The Perfect Programming Language

This section was labeled under Programming

Programming incorrectness

First of all I do not like programming languages wars and I believe they are vastly stupid; every programming language out there had its own views that matched with feasible many usages. I claim however that some common ways of designing some languages were not optimal at all, and were indeed influenced by external forces other than the ideality of the design (corporate interests is a widely acknowledged example).

My main use case for a programming language regular software engineering, although sometimes I do scientific computing, most programming languages out there fit for my ’scientific’ needs. My favorite language for scientific computing currently is Julia, my favorite language generally is Go. The following table shows the aspect that I consider when I pickup a programming language for my need. I will only list the language I know and tried.

Language/Feature Fast and Performant No Centralized Package Repository No Exception Handling Static Linking Supported Usable REPL (Officially Supported) No Classical OOP Parallel Computing with Coroutines and Channels Supported (Bonus)
Common Lisp (SBCL) Yes Yes/No No No Yes No No
Julia Yes No No Yes Yes Yes Yes
Go Yes Yes Yes Yes Yes Yes Yes
Rust Yes No Yes Yes No Yes Yes
Python No No No No (interpreted) Yes No No
C Yes Yes Yes Yes No Yes Yes (sorta, using libmil)
C# Yes (sorta of) No No Yes Yes No Not sure

Side notes:

Exception handling

Some of the features that I look for are obvious; however some of them might be questionable for other people, for example people who have been using C#/Java for all of their life would be surprised that someone does not like exceptions, this is like saying if statements are harmful.

However, this is only because this is what people used to engage with, but when you think carefully about exceptions you can see that in their essences they are nothing different than GOTO calls (which you rarely find someone nowadays question them being considered harmful), actually one might consider arguing about some benefits over using GOTO calls sometimes; but if you deeply compare GOTO with exceptions, you will see how terrible exceptions are, that is, they include only the bad parts of GOTOs. There is a type of GOTO calls that was just bad that no body talks about, and it was actually the one from which all this hate emerged against GOTO calls, that’s BASIC’s GOTO. C-like GOTOs are much more constrained compared to the former, yet if you compare both to exceptions, exceptions are akin to classical BASIC’s GOTOs. Since I do not like this post to be transferred into a “case against the exception handling”, I’d recommend reading the following; Edsger W. Dijkstra’s A Case against the GOTO statement with exception handling in mind (i.e. replace every occurrence of GOTO with try catch throw) and reading Dave Cheney’s Why Go gets exceptions right.

I like to mention that my first programming language was C/C++. Then I learned C#, which I still believe is a very nice language (I will try to discuss it later here). When I learned C# for the first time and I shot myself in the foot I experienced exceptions for the first time. I was really surprised by how errors were being handled, I felt something really strange: it could not be that naive. Of course I did not tell myself that because what I did in C (which was just a variable passed by reference indicates whether everything is alright, like the Go way, the way I prefer: simple) was actually no error handling at all. I told myself it might be a screwed way of designing the language but I tried just to get adapted to it (like probably everyone did) once I discovered that this is the way to handle errors in many other languages as well; think about this flow, you are using a library that uses set of other libraries, it does set of complicated scenarios, including using multiple http clients, intensive writing/reading operation on the file system, high memory usage, etc..

Now each of these might have many factors contributing a failure, the http client might have an issue during the early initialization due to inadequate memory or something (actually any other possible reasons), the file system might return an error code because of mismatching/unsafe/unsatisfying permissions, or it might be full, it might be busy, and so on and so forth: too many possibilities, computers are complex.

In exception handling, you can just use a single outer catch to all these scenarios:

// in your main function:
try
{
  //  start your program here
}

// genaric type to catch
// any possible exceptions
// inherits this class
//        ^
//        |
catch (Exception e)
{
  //  Block of code to handle errors
  // some debuging flags here
  System.SoyFriendly.SoyendFriendlyMessageToUser("sorry bro something went wrong")
}

However, a sophisticated software developer will have many exception handling for cases like the ones I mentioned above; like memory and network errors. The problem here is, there is no way the developer can handle all possible exceptions Some language designer had the decision to make their STD never throw exceptions, however the majority of languages that use exception use it in their STDs too. This makes the number of the possible exception very huge. so they are going only to fix things that either their user will report them later with some logs, or things that are obvious to occur (network errors are likely to happen for example).

This makes the use of that outer try..catch inevitable unless you do not care about the user experience. This engenders many possible scenarios that might have been manageable by the programmer to get out till they add it to their handled exceptions in some new versions. What is the alternative? the programmer should (or must) handle all the possible cases, which is the case with some new languages like Go and Rust.

Centralized Package Repository

This is not a major issue, but it is very annoying in my opinion, which is just as common as exception handling or even more. I think that people will consider it very soon as the internet is moving more towards decentralization and distribution. You can see the issue of centralization when you look at the number of “please”s in their repository quicklisp/quicklisp-projects. The Ultralisp Repository tries to resolve this issue for the Common Lisp programming language.

However this issue of “approving” packages is not common (yet) I think it starts to be a little common with Julia, though the language makes it very easy to install package directly from any git repository, just like Go does. , I used to use nuget and I used cargo and both are actually very okay to use, yet there are 0 guarantee that they are going to stay like that or even that they will ’behave’ right. This is because the maintainers have the whole absolute power, can we be sure that Microsoft will not add some 0.3$ subscription to be able to use nuget? Can we be sure that Mozilla maintainers will not decide that programming is bad and just dropout cargo for good? Will all of these possibilities have very low likelihood, however, there is a very important lesson that all of you might have learned from software design: we never trust, we constrain; you wouldn’t give your user all permissions and trut them that they are faithful nice people.

This is the cause with centralized package repositories, we have nothing but to trust the maintainers who have all the power, if they do not put restrictions already on who is going add his package or why (like quicklisp does), no one can guarantees that they do not misconduct due to whatever reason towards some package. Remember the Rust 1.65.0 Announcement? When the Rust team added some political correctness spices to their release note about the Mahsa Amini incident. Well what will be their reaction to a package in cargo that all it does is printing some pro-Irani propaganda about the deceased? There should be no one to supervise whether X is right or wrong in programming environments.

Programmers can make languages horrible

I think last 2 sections elaborate in the most 2 controversial things in my view, though unlike Centralized Package Repository, I do not think that Exception handling is ultimately bad, still I think it should not be allowed. This also applies to things like macros and inheritance.

Common Lisp is the most language that I think the following applies to it. Actually I want you to have a look at this post from Hacker News:

I thought Lisp was suppose to be simple in that: it's all just lists.

I thought everything would just be s-expressions, and be consistent, so it would be
easy to read to figure out what is going on.

But it seems like there are so many special constructs and macros, that make it hard
to read. And behind the scenes of these macros it gets really complicated. Whereas in
other languages its readable the whole way down.

E.g. How am I suppose to read this? How does it de-construct to s-expressions...and
does it even? What is implemented natively in the interpreter? Does that language
have built-in keywords?

I thought everything was suppose to be like: `(left . (left . right) )`.

    (loop for i in '(1 2 3)
        when (> i 1)
        return i)
It seems as if there are actually a ton more special case primitives I need to know,
when I could get away with a lot less syntax in other languages to be productive.

Like maybe there is some simplicity at the very bottom, but that doesn't seem to
matter in day-to-day programming.

Another example, the first think I see when I look at the language basics of how to
make a function:

https://lispcookbook.github.io/cl-cookbook/functions.html:

    (defun  (list of arguments)
      "docstring"
      (function body))
How do I read this as an s-expression?

Want I want you to notice here is the macro part (loop for), this macro was very controversial back in the day, many people believed that it is not “lispy enough” to be used, however, it was “ok” since it was “up to you to use it or not”, and it ended up being a part of the common lisp implementation.

Another thing to mention is that I’m one of the people who believe that inheritance is pretty much okay, even multiple inheritance actually which I used to use in C++ sometimes, however, you might have noticed that I really do not like to use languages that do support inheritance

This applies to another thing in Common Lisp, the Common Lisp Object System (CLOS) which implements the old (hesitated to add ’good’) classical OOP. I believe that it is one of the greatest things about Common Lisp, but what I’ve always and always noticed, that people are really, really abusing it badly, seems applies to inheritance, multiple inheritance and exceptions.

Back in the day when I was learning programming for the first time, in C++, and I learned that many languages adds restrictions on things like multiple inheritance and even inheritance, I asked myself: why? I mean, well they are nice things it should be up only to the programmer to decide when to use it or not.

This is still true, however, when you think about your experience in the software industry, you understand how much consideration of the community matters as well.

Some reason that I recall for my experience with JavaScript was very bad, was that unlike other languages that I used back in the day, JavaScript had many, so many incomplete developers who just came from some twitter hips and whatnot. Why does this matter? Well, many times you are going to use packages and libraries that this community did build. Here is it: in the modern software industry, the community surrounding a programming language actually matters too.

And this what happened with language allowing inheritance, exceptions, GOTOs, and the like, people just abused it and the language became very horrible to use because many packages became badly written.

Footnotes:

1

Some language designer had the decision to make their STD never throw exceptions, however the majority of languages that use exception use it in their STDs too. This makes the number of the possible exception very huge.

2

I think it starts to be a little common with Julia, though the language makes it very easy to install package directly from any git repository, just like Go does.


I seek refuge in God, from Satan the rejected. Generated by: Emacs 29.4 (Org mode 9.8). Written by: Salih Muhammed, by the date of: 2023-08-10 Thu 09:35. Last build date: 2024-11-07 Thu 22:18.