1  Getting Your Money’s Worth

\(\newcommand{\TirName}[1]{\text{#1}} \newcommand{\inferrule}[3][]{ \let\and\qquad \begin{array}{@{}l@{}} \TirName{#1} \\ \displaystyle \frac{#2}{#3} \end{array} } \newcommand{\infer}[3][]{\inferrule[#1]{#2}{#3}} \)

This course is about principles, concepts, and ideas that underly programming languages. But what does this statement mean?

As a student of computer science, it is completely reasonable to think and ask, “Why bother? I’m proficient and like programming in Ruby. Isn’t that enough? Isn’t language choice just a matter of taste? If not, should I be using another language?”

Certainly, there are social factors and an aspect of personal preference that affect the programming languages that we use. But there is also a body of principles and mathematical theories that allow us to discuss and think about languages in a rigorous manner. We study these underpinnings because a language affects the way one approaches problems working in that language and affects the way one implements that language. At the end of this course, we hope that you will have grown in the following ways.

1.1 You will be able to learn new languages quickly and select a suitable one for your task.

This goal is very much a practical one. Languages that are “popular” vary quickly. The TIOBE Programming Community Index surveys the popularity of programming languages over time. While it is just one indicator, the take home message seems to be that a large number of languages are active at any one time, and the level of activity of any language varies widely over time. The “hot” languages now or the languages that you study now will almost certainly not be the ones you need later in your career.

There is a lingo for describing programming languages. The introduction to any programming language is likely to include a statement that aims to succinctly captures various design choices.

Python

“Python is an interpreted, interactive, object-oriented programming language. It incorporates modules, exceptions, dynamic typing, very high level dynamic data types, and classes.” [4]

OCaml

OCaml offers “a power type system, equipped with parametric polymorphism and type inference […], user-definable algebraic data types and pattern matching […], automatic memory management […], separate compilation of stand-alone applications […], a sophisticated module system […], an expressive object-oriented layer […], and efficient native code compilers.”

Haskell

Haskell is “a polymorphically statically typed, lazy, purely functional language, quite different from most other programming languages.”

Scala

“Scala is a blend of object-oriented and functional programming concepts in a statically typed language” [3].

At this point, it is understandable if the above statements seem as if they are written a foreign language.

1.2 You will gain new ways of viewing computation and approaching algorithmic problems.

There are fundamental models of computation or programming paradigms that persist (e.g., imperative programming and functional programming). Most general-purpose languages mix paradigms but generally have a bias. These biases can shape the way you approach problems.

For natural languages, linguistic relativity, the hypothesis that the language one speaks influences the way one perceives the world, is both tantalizing and controversial. Many have espoused this notion to programming languages by analogy. Setting aside the controversy and assuming at least a kernel of truth, practicing and working with different programming models may expose ideas in new contexts. For example, MapReduce is the programming model created by Google for data processing on large clusters inspired by the functional programming paradigm [1].

This course is not a survey of programming languages present and past. We may make references to programming languages as examples of particular design decisions, but the goal is not to “learn” lots of languages. The analogy to natural languages is perhaps apt. It does not particularly help one understand the structure of natural languages by learning to say “hello” in as many as possible.

1.3 You will gain new ways of viewing programs.

The meaning of program is given by how it executes, but a program is also artifact in itself that has properties. What a program does or how a program executes is perhaps the primary way one views programs—a program computes something. At the same time, a program can be transformed into a different one that “behaves the same.” How do we characterize “behaves the same”? This question is one that can be discussed using programming language theory.

It is also a question of practical importance for language implementation. A compiler translates a program that a human developer writes into one a computational machine can execute. The compiler must abide by the contract that it outputs a program for the machine that “behaves the same” as the program written by the developer.

1.4 You will gain insight into avoiding mistakes for when you design languages.

When (not if!) you design and implement a language, you will avoid the mistakes of the past. You may not design a general-purpose programming language, but you may have a need to create a “little” configuration, mark-up, or layout language. “Little” languages are often created without much regard to good design because they are “little,” but they can quickly become not so “little.”

Avoiding bad language design is tricky. Experts make mistakes, and mistakes can have long-lasting effects. Turing award winner Sir C.A.R. Hoare has called his invention of the null reference a “billion dollar mistake” [2].

1.5 You will be able to use AI assistants to accelerate your creative design.

Generative AI for programming is here to stay. AI is amazing accelerator for creative design by drawing on what has been done before—if you can evaluate what it gives you.

Understanding how programs and programming languages are composed enables to effectively understand what makes sense and what needs refinement to create something new.