Thursday, March 5, 2020

Programming languages differ

A developer recently ranted about the Go language. The rant was less about the language and more about run-time libraries and interfaces to underlying operating systems and their file systems. The gist of his rant is that Go is not a suitable programming language for performing certain operations on certain operating systems, and therefore he is "done" with Go.

The first part of his rant is correct. I disagree with the conclusion.

We have the idea that programming languages are general-purpose, that any language can be used for any problem. But programming didn't start that way. Programming languages started unequal, with different languages designed for different types of computing. And while languages have become less specific and more general-purpose, they are still not equal.

I think our idea about a general-purpose programming language (or perhaps an all-purpose programming language) started with the IBM System/360  in the 1960s and the PL/1 programming language.

Prior to the System/360, computers had specific purposes. Some computers were designed for numeric processing, and others were designed for transaction processing. Not only were computers specific to a purpose, but programming languages were, too. FORTRAN was for numeric processing, and used on computers built for numeric processing. COBOL was for transaction processing, and used on computers built for commercial processing.

After IBM introduced the System/360, a general-purpose computer suitable for both numeric and commercial processing, it introduced PL/1, a general-purpose programming language suitable for numeric and commercial processing. (A very neat symmetry, with general-purpose hardware using a general-purpose programming language.)

PL/1 saw little popularity, but the notion of a general-purpose programming language did gain popularity and still dominates the our mindsets.We view programming languages as rough equals, and the choice of language can be made based on factors such as popularity (a proxy for availability of talent) and tool support (such as IDEs and debuggers).

There are incentives to reinforce the notion that a programming language can do all things. One comes from vendors, another comes from managers, and the third comes from programmers.

Vendors have an incentive to push the notion that a language can do everything -- or at least everything the client needs. Systems from a vendor come with some languages but not all languages. Explaining that your languages can solve problems is good marketing. Explaining that they cannot solve every problem is not.

The managers who purchased computers (which were expensive in the early days) wanted validation of their selection. They wanted to hear that their computer could solve the problems of the business. That meant believing in the flexibility and power of the hardware, and of the programming languages.

The third group of believers is programmers. Learning a programming language takes time. The process is an investment. We programmers want to think that we made a good investment. Admitting that a programming language is not suitable for some tasks means that one may have to learn a different programming language. That's another investment of time. It's easier to convince oneself that the current programming language is capable of everything that is needed.

But different programming languages have different strengths -- and different weaknesses. Programming languages are not the same, and they are not interchangeable.

COBOL is good for transaction processing, especially with flat files. But I would not use it for word processing or games.

FORTRAN is good for numeric processing. But I would not for word processing, nor for transaction processing.

Object oriented languages such as C++, Java, and C# are good for large applications that require structure and behavior that can be defined and verified by the compiler. (Static types and type checking.)

BASIC and Pascal are good for learning the concepts of programming. Both have been expanded in many ways, and have been used for serious development.

R is good for statistics and rapid analysis of numeric data, and the visualization of data. But I would not use it for machine learning.

Perl, Python, and Ruby are good for prototyping and for small- to medium-size applications. I would not use them for large-scale systems.

We should not assume that every language is good for every task, or every purpose. Languages (and their run-time libraries) are complex. They can be measured in multiple dimensions: complexity of the language, memory management and garbage collection, type safety, support tools, library support, connections to data bases and data sources, vendor support, community support, and more. Each language has strengths and weaknesses.

The developer who ranted against the Go language had criticisms about Go's handling of filesystems on Windows. His complaint is not unfounded; Go has a library that expects a Unix-like filesystem and not a Windows filesystem, and works poorly with Windows. But that doesn't mean that the language is useless!

An old joke tells of a man who consults a doctor. The man lifts his arm and says "Doc, it hurts when I do this." The doctor replies, "Well, don't do that!" While it gets laughs, there is some wisdom in it. Go is a poor language for handling the Windows filesystem; don't use it for that.

A more general lesson is this: know your task, and know your programming language. Understand what you want to accomplish, at a fairly detailed level. Learn more than one programming language and recognize that some are better (at certain things) than others. When selecting a programming language, make an informed decision. Don't write off a language forever because it cannot do a specific task, or works poorly for some projects.

No comments: