The Study of Programming Languages

Hello! Since you are here, you are probably wondering why the study of programming languages a worthy pursuit. “What’s in it for me?” you may be asking. Fear not—there are benefits. “How should I study them?” you may be asking. There are good answers to this question, too.

Why Study Programming Languages?

Because benefits.

Professional Benefits

Studying programming languages will help you:

So basically, you will become happier and make more money.

Social Benefits

Studying programming languages may even enable you to:

Is it Really a Field of Study?

The ACM says yes!

Knowledge AreaCodeSome Topics
Algorithms and ComplexityALAlgorithmic Analysis • Algorithmic Strategies • Data Structures and Algorithms • Automata • Computability • Computational Complexity
Architecture and OrganizationARDigital Logic and Digital Systems • Machine-level Data Representation • Assembly-Level Machine Organization • Memory System Organization and Architecture • Interfacing and Communication • Functional Organization • Multiprocessing and Alternative Architectures • Performance Enhancements
Computational ScienceCNModeling and Simulation • Processing • Interactive Visualization • Data, Information and Knowledge • Numeric Analysis • Symbolic Computation • Mathematical Modeling • High-Performance Computing
Discrete StructuresDSLogic • Sets, Relations, and Functions • Proof Techniques • Basics of Counting • Graphs and Trees • Discrete Probability
Graphics and VisualizationGVMedia Applications • Digitization • Color Models • Rendering • Modeling • Animation • Visualization
Human-Computer InteractionHCIInteractive Systems • Testing • Collaboration and Communication • Statistical Methods • Human Factors • Mixed, Augmented, and Virtual Reality
Information Assurance and SecurityIASDefensive Programming • Threats and Attacks • Network Security • Cryptography • Web Security • Platform Security • Policy and Governance • Digital Forensics • Secure Software Engineering
Information ManagementIMDatabase Systems • Data Modeling • Indexing • Key-Value, Document, Relational, and Graph Databases • Query Languages • Transaction Processing • Distributed Databases • Physical Database Design • Data Mining • Information Storage and Retrieval • Multimedia Systems
Intelligent SystemsISKnowledge Representation and Reasoning • Search • Machine Learning • Reasoning Under Uncertainty • Agents • Natural Language Processing • Robotics • Speech Recognition and Synthesis • Perception and Computer Vision
Networking and CommunicationNCNetworked Applications • Reliable Data Delivery • Routing and Forwarding • Local and Wide Area Networks • Resource Allocation • Mobility • Social Networking
Operating SystemsOSOperating System Organization • Concurrency • Scheduling and Dispatch • Memory Management • Security and Protection • Virtual Machines • Device Management • File Systems • Realtime and Embedded Systems • Fault Tolerance • System Performance and Evaluation
Platform-Based DevelopmentPBDWeb Platforms • Mobile Platforms • Industrial Platforms • Game Platforms
Parallel and Distributed ComputingPDParallel Decomposition • Communication and Coordination • Parallel Algorithms, Analysis, and Programming • Parallel Architecture • Parallel Performance • Distributed Systems • Cloud Computing • Formal Models and Semantics
Programming LanguagesPLObject Oriented Programming • Functional Programming • Event-Driven and Reactive Programming • Type Systems • Program Representation • Language Translation and Execution • Syntax Analysis • Semantic Analysis • Code Generation • Runtime Systems • Static Analysis • Concurrency and Parallelism • Type Systems • Formal Semantics • Language Pragmatics • Logic Programming
Software Development FundamentalsSDFAlgorithms and Design • Fundamental Programming Concepts • Fundamental Data Structures • Development Methods
Software EngineeringSESoftware Processes • Project Management • Tools and Environments • Requirements Engineering • Software Design • Software Construction • Software Verification and Validation • Software Evolution • Software Reliability • Formal Methods
Systems FundamentalsSFComputational Paradigms • Cross-Layer Communications • State and State Machines • Parallelism • Evaluation • Resource Allocation and Scheduling • Proximity • Virtualization and Isolation • Reliability through Redundancy • Quantitative Evaluation
Social Issues and Professional PracticeSPSocial Context • Analytic Tools • Professional Ethics • Intellectual Property • Privacy and Civil Liberties • Professional Communication • Sustainability • History • Economics of Computing • Security Policies, Law, and Crime

You might even find the study of languages, especially in its theoretical side, to be even more fundamental than the favorite of job interviewers—data structures and algorithms. Language theory helps us organize our thoughts around how information is both expressed and manipulated. Without a way to represent data or computation, we really wouldn’t have computer science.

How to Study Programming Languages

Self-check time! Make sure you know what a programming language is.

Did you read the article? Okay, let’s lay out a study plan.

An effective study of programming languages has three parts:

Learn Languages

Learn a bunch of existing languages, and understand how each expresses and implements various concepts

Learn Concepts

Study many concepts, and understand how each is expressed in a variety of languages

Learn Formalisms

Learn and be able to apply mathematical precision to syntactic and semantic descriptions.

The study of those three aspects should be carried out in the proper contexts:

History

Understanding history is essential for learning any discipline and the study of programming languages is no exception.

Pragmatics

Programs and Programming Languages are written by people for people. Understanding the human use and perception of languages is crucial.

Let’s give a very brief overview of these five items.

History

Your study of programming languages is enhanced when done in a historical context. Programming Languages do have a rich history. There have been many books and articles written on the History of Programming Languages (HOPL). It’s really fascinating! And super important, too.

We can’t boil the history of the field into a couple paragraphs, but there are some historical highlights worth mentioning to whet your appetite:

Early History
Prior to the 1940s we have the Jacquard machine and Ada Lovelace's programming of the Analytical Engine. Plankalkül is designed in the early 1940s but never gets popular. It’s a high-level language, yes, but mostly symbolic.
1950s-1960s Rise of natural language-like languages
Grace Hopper leads the COBOL effort (business computing), John McCarthy leads Lisp (AI), John Backus leads Fortran (scientific computing). Early Algol becomes popular and eventually we get behemoth multi-purpose languages like Algol 68 and PL/1.
1970s The structured programming revolution begins
Languages providing information hiding, such as Modula, CLU, Simula, Mesa, and Euclid attempt to address the “software crisis.” Structured and modular features are bolted on to earlier languages.
1980s Object-orientation takes over the world
Though begun in the 1960s with Simula and refined in the 1970s at Xerox PARC with Smalltalk, OO—or approximations to it—explodes in the 1980s with C with Classes (since renamed C++), Objective-C, Eiffel, and Self. Earlier languages such as Lisp and Pascal gain OO features, becoming Common Lisp and Object Pascal, respectively.
1990s The World Wide Web appears
Perl becomes popular. Java, JavaScript, and PHP are created with web applications in mind.
2000s: Interest in established dynamic languages such as Ruby takes off
Scala shows that static languages can feel dynamic. Clojure arrives as a dynamic, modern Lisp, leveraging Java’s virtual machine.
2010s: Old things become new again
Multicore processors and “Big Data” revive interest in functional programming. Older languages such as Python and R, and the newer Julia language, find use in data science. Net-centric computing and performance concerns make static typing popular again as Go, Rust, and Swift challenge C and C++ for native applications.

Next, you’ll need to go much deeper. Here are some great reads and watches:

Many people don’t realize what incredible work happened in the 1960s and 1970s. Learn about this era in this informative and entertaining look into what this work could have turned into, so much sooner that it did, if it did:

Exercise: Watch this video, please. Follow along with the video notes and references.

Follow up with your own web searches for “History of Programming Languages” or “Evolution of Programming Languages.”

Learning Languages

When studying actual languages, you should learn:

Understanding a language’s motivation for existence is essential. It is unfair to criticize a language for doing a bad job in an area which it was never intended to be used for.

Some significant languages

Here are a few languages that for some reason or another rate as significant:

Motivation

Here are some languages and their motivations for being created. In some cases, the language found a niche outside the purpose for which it was designed. But the point is that some problem was seen as significant enough to warrant a new language.

Exercise: Java is an example of a language whose primary use turned out to be completely different from its original design purpose. What are Java’s niches today?

Where to learn more

Language lists, comparisons, and taxonomies:

As you learn more languages, you will start to enjoy Rosetta Code, and hopefully contribute!

Learning Language Concepts

In addition to learning a dozen or so programming languages, you will want to accumulate a good deal of organized knowledge about the important (language-independent) concepts that underlie programming languages. Such concepts include:

Mathematical Formalisms

A study of just about anything can be enhanced with mathematical and logical precision. For programming languages, we want a way to specify, unambiguously, exactly what are the legal programs in a language, and what exactly they mean. Natural language is open to interpretation and fuzziness and ambiguity, so we would like to bring in some mathematical machinery. Topics we use include logic, set theory, lambda calculus, automata theory, computation theory.

Math is used to assist with the definition of two aspects of language: syntax (structure) and semantics (meaning).

Syntax

A programming language gives us a way structure our thoughts. A program’s structure is determined by the syntax of the language. The syntax defines which strings of characters are valid programs, and if valid, how the characters are grouped into words (called tokens) and how the words are grouped into phrases (such as declarations, expressions, statements, etc.)

A syntax is normally defined formally and mathematically, using objects such sets, sequences, alphabets, and grammars.

Syntactic formalisms are well understood in computer science and fluency with at least one formalism is an expectation of undergraduate computer science students and most programers. Among those you will encounter in your study of programming languages are: BNF, EBNF, ABNF, plain old Context-Free Grammars, Syntax Diagrams, and (my favorite) Parsing Expression Grammars.

Semantics

The semantics of a language gives meaning to its programs. We need to be able to precisely and unambiguously define the meaning (or effect) of every program. This requires understanding and using sets, relations, functions, and similar constructs. Theories of functions such as the λ-Calculus are very helpful here.

Unlike syntax, for which formalisms are straightforward, mathematical approaches to semantics are generally undertaken only in graduate computer science courses.

See the Wikipedia articles on Semantics and Semantics in Computer Science.

Pragmatics

Pragmatics does not affect the formal specification of programming languages; however, pragmatic concerns must guide your design of a programming language—if you want it to be easy to read, easy to write, and able to be implemented efficiently. Pragmatics encompasses:

One of the more common ares of study within pragmatics is how one evaluates a language.

Criteria for Evaluation

Reasonable people know that all languages have their pros and cons. But why are some things pros and other things cons? There are certain technical criteria:

Is the language:

Also see Wikipedia’s Programming Language Comparison article.

There are non-technical, subjective criteria, too. Good and successful are not the same! Success comes from:

Exercise: What else can you think of that makes people want to use a particular language?

Expressiveness

Expressiveness is a pragmatic concern, too, influencing how a language can be wielded to say what needs to be said. Some languages want to be verbose, low-level, or “close to the machine” and others want to be terse or expressive. Here’s the way different languages allow you to express a function to return the sum of the squares of even numbers in a list. In class, we’ll discuss the pragmatic issues that arise in each:

int sum_of_even_squares(int* a, unsigned int length) {
    int total = 0;
    for (unsigned int i = 0; i < length; i++) {
        if (a[i] % 2 == 0) {
            total += a[i] * a[i];
        }
    }
    return total;
}
func sumOfEvenSquares(a []int) int {
    total := 0
    for _, x := range a {
        if x % 2 == 0 {
            total += x * x
        }
    }
    return total
}
function sumOfEvenSquares(a) {
  return a.filter(x => x % 2 === 0).map(x => x**2).reduce((x, y) => x + y, 0)
}
public static int sumOfEvenSquares(int[] a) {
    return IntStream.of(a).filter(x -> x%2==0).map(x -> x*x).sum();
}
func sumOfEvenSquares(_ a: [Int]) -> Int {
    return a.filter{$0 % 2 == 0}.map{$0 * $0}.reduce(0, +)
}
(defn sum-of-even-squares [a]
  (->> a (filter even?) (map #(* % %)) (reduce +)))
def sum_of_even_squares(a):
    return sum(x*x for x in a if x % 2 == 0)
sumofevensquares: {+/x[&~x!2]^2}

Related to expressiveness is the idea of code as art, or art as code. Here’s a discussion of what this actually means:

Popularity

There are countless numbers of ways to measure popularity! You really can’t make popularity statements without stating your measure. Then people will argue whether your measure is even valid. 🤷‍♀️ Nevertheless, it’s fun to look at this stuff from time to time.

RedMonk has a language ranking scheme that combines pull requests on GitHub and questions on StackOverflow. (One could argue that this measures how confusing a language is too...maybe most of the StackOverflow questions are language complaints?) Here is the ranking from June 2021:

redmonk.png

RedMonk gives these rankings:

  1. JavaScript
  2. Python
  3. Java
  4. PHP
  5. CSS
  6. C++#
  7. C#
  8. TypeScript
  9. Ruby
  10. C
  11. Swift
  12. R
  13. Objective-C
  14. Shell
  15. Scala
  16. Go
  17. PowerShell
  18. Kotlin
  19. Rust
  20. Dart

Another ranking system, by Tiobe, ends up with a radically different top 20. They say: “The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. Popular search engines such as Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube and Baidu are used to calculate the ratings.”

Here’s a current take:

But what makes a language popular? MPJ has thoughts:

Understanding Evaluation Tradeoffs

You can’t have everything, it seems:

Exercise: Think up some other tradeoffs.
No Competition!

Don’t make the mistake of thinking programming languages are like sports teams—they don’t compete against each other. Don’t root for one to “win.”

Realize that languages serve different purposes and are often used together to build systems.

Summary

We’ve covered:

  • The professional benefits to the study of programming languages
  • The social benefits to the study of programming languages
  • Three knowledge areas: languages, concepts, formalisms
  • Two contexts: history, pragmatics
  • Some significant languages
  • A small taxonomy of programming language concepts
  • A brief history of programming languages
  • A brief look at syntax, semantics, and pragmatics
  • Ways to evaluate programming languages