Evolution of Programming Languages

Language Wars and Picking the Right Tool for the Job


Learning Objectives

  • You know of “language wars” and of some of the classic arguments for and against different programming languages.
  • You understand the importance of performance, readability, and the ecosystem surrounding a programming language.

A classic debate, often referred to as the “language wars”, evolves around the merits of different programming languages. This debate, although childish, is still at times present.

Classic Arguments and Examples

As an example, a classic argument against Java from the Python community might be that Java is verbose and requires more boilerplate code. On the other hand, Java developers might argue that Python’s dynamic typing can lead to runtime errors that could have been caught at compile time, that maintaining large Python programs can be a horror, and that Python performs poorly in real applications.

Similarly, a student in an introductory programming course might also argue that Python is better as writing a program that prints “Hello, World!” takes just one line in Python, while in Java it takes several lines — as demonstrated by the following examples. First, in Python, we can write just one line for the program.

print("Hello, World!")

While in Java, programs are encapsulated in a main method, similar to e.g. Dart and Rust. The command for printing is also more complex — println is often used instead of just print to print a line.

void main() {
  println("Hello, World!");
}

Huuge difference, right? 😄

If you’re familiar with Java but the above feels unfamiliar, it might be because the above example uses a relatively new feature called implicitly declared classes and instance main methods.

Other arguments include slowness of a specific language, readability of syntax, community and support, learning curve and productivity, and so on..

Loading Exercise...

Performance, Readability, and Ecosystem

Which language to pick for the job is a complex question. The debate often centers around key factors such as performance, readability, and the ecosystem surrounding a language. These factors can dramatically affect the development process and the final product.

Performance

For applications where raw speed and low-level control over system resources are critical, languages like C or Rust are often preferred. Consider a simple example that sums numbers from 1 to 1,000,000.

The following program in C demonstrates a straightforward loop that sums numbers from 1 to 1,000,000.

#include <stdio.h>

int main(void) {
    long long sum = 0;
    for (int i = 1; i <= 1000000; i++) {
        sum += i;
    }
    printf("Sum: %lld\n", sum);
    return 0;
}

While the above program would be more efficient to execute, the following Python program is more concise and easier to read.

print("Sum:", sum(range(1, 1000001)))

In this comparison, the C version offers fine-grained control and potential performance benefits when compiled and optimized, whereas the Python version is much more concise and easier to read, even though it might not perform as well in computation-intensive scenarios.

There are a range of benchmarks and comparisons available online that can help you understand the performance characteristics of different languages and their implementations. When studying the benchmarks, do note that the performance of a language can vary based on the specific task and the quality of the implementation.

As an example, see the following:

Readability

Readability is another factor. Languages like Python and Ruby emphasize clarity. For example, performing the above summing task in Python is achieved in one line of code, which many find easier to understand and maintain.

Similarly, reading a file line by line in Python might be more straightforward than e.g. doing the same in Java.

Python Example (Readability and Conciseness):

# Python: Read a file line by line
with open('file.txt') as f:
    for line in f:
        print(line)

Java Example (More Verbose Syntax):

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class ReadFile {
    public static void main(String[] args) {
        try {
            Files.lines(Path.of("file.txt"))
                 .forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The readability of the language helps in remembering and writing code. This is in particular useful for novice programmers. There’s evidence, for example, that highlights that programming languages that conform with research on programming language usability are easier to learn and use; similarly, languages like Perl can be similarly hard to learn than languages where some of the syntax is chosen with a random number generator.

For additional details, see an empirical comparison of the accuracy rates of novices using the quorum, perl, and randomo programming languages.

Ecosystem

Programming languages do not live in a bubble, but come with an ecosystem. The ecosystem includes the libraries, frameworks, community support, and development tools that surround a language. For instance, JavaScript’s rich ecosystem as made it the de facto language for modern web development, while Java’s ecosystem is strong in enterprise software development.

When picking a language for a task, it is sensible to also consider the availability of libraries and tools that can help with the task. A language with a large ecosystem can boost productivity, while a smaller ecosystem might require more custom development and maintenance, leading to reinventing the wheel.

Need to Know Multiple Languages

If there’s a takeaway in the above, it is that every language has strengths and weaknesses. A language that excels in performance (like Rust) might be less readable and more verbose compared to a high-level language like Python. Conversely, while Python is great for rapid prototyping and maintainability, it may fall short in performance-critical applications where other languages might be more appropriate. Knowing multiple languages allows developers to pick a better tool for each task, and to understand the trade-offs involved in each choice.

Loading Exercise...

Criteria for Picking a Language?

When it comes to choosing a programming language for a task, there is rarely a “correct” answer. Instead, the decision involves evaluating various criteria based on project needs, team expertise, and long-term goals.

Here are a few items that might be meaningful to consider.

  • Project Requirements: For tasks that require direct hardware access or real-time performance, low-level languages like Rust might be more appropriate. For projects that require more rapid development and prototyping, and do not need low-level access, languages like JavaScript, Python or even Dart (esp. for mobile) might be better.

  • Existing Skills: The existing skill set of the team is another criterion. A team that is already well-versed with a specific technology might be more productive using that technology rather than learning a new technology. At the same time, sticking with a technology can lead to stagnation and in the long run problems with hiring, as technologies can become outdated.

  • Ecosystem: The availability of libraries, frameworks, and community support can heavily influence the choice. For example, if your project involves web development, JavaScript frameworks like React or Svelte might be sensible to consider due to their popularity and extensive ecosystem.

  • Long-Term Maintainability and Scalability: When picking technologies, it is also meaningful to consider how easy it will be to maintain the project over time. New technologies might be exciting, but if they are not well-documented or have a small community, maintaining the project might become a challenge, especially as new technologies rarely offer long-term support.

Loading Exercise...