Session 1
A Gentle Introduction to the Study of Programming Languages
How Do We Study Programming Languages?
This is a course on programming languages. (More on the course title later.) Just how do we go about studying programming languages?
We could learn a bunch of new programming languages and study their features. Each new language gives us new ways to compare and contrast the choices that language designers make. We would be able to reflect on the different languages and come to a broad understanding on the field.
This approach has some challenges. It takes a considerable amount of time to learn several new languages well. And if we did manage to, would that even teach us much?
Not necessarily. We would have to select the languages carefully. If we learned Java, then C##, and then C++, we would have seen many of the same ideas in three different forms — and sometimes, even the form is not all tha different! What's worse, we would have had to deal with a lot of extraneous details introduced by each language.
Perhaps instead we could study different kinds of languages.
What kinds of programming languages are there? How do we classify languages?
Pause for a moment and write down some of the labels you have heard people use to describe programming languages.
There are a number of different labels we often apply to programming languages, or to the boxes we put them in:
- high-level vs low-level
- procedural
- functional
- object-oriented (OO)
- graphical
- statically typed
- stack-based
- LL(1)
- server side vs client side
- compiled vs interpreted (vs JIT)
- declarative
Many of these terms may be new to you. That's okay. But they show us how big the world of programming languages.
What is an example of a declarative language? SQL
Functional? Haskell
Object-oriented? Java
What questions can we ask about all these boxes? What questions should we ask?
- Which kind of language is best?
- Which kind of language is best for which purposes?
- Perhaps most importantly: Are there more boxes?
Yes, there are more:
- markup, like HTML and Markdown
- scripting languages, like bash or JavaScript — or Python
Wait a minute. Isn't JavaScript is a functional language? Isn't Python object-oriented?
This confusion is not accidental. Our categories cut across several different dimensions for labeling languages, including programming style, intended use, complexity, and type of grammar.
Even on the issue of style, we encounter confusion. Consider Python or JavaScript. They fit nicely into several different programming language boxes. Language designers sometimes speak of "multi-paradigm" languages, which are designed specifically so they belong in several different boxes. Is "multi-paradigm" a new box for our list?
Ack! What are we to do?
Pop Quiz!
Just kidding... Please complete this short survey for me:
-
List up to five programming languages you know best.
For each language on your list, say where you learned it: in class, at work, on your own, or some other way. - Of these languages, which is your favorite?
- List one feature of this language that you like. Why do you like it?
- List one feature of this language that you would like to improve or change. Why?
How you decide which language is your favorite reveals something about how you think about programming languages right now.
We could ask many more questions about programming languages:
- Why do we have all these different languages?
- Can one language be better than another language?
- Can one language be easier to learn than another language?
- Can a programming language be beautiful? If so, how?
- Can a program be beautiful?
These aren't trick questions. After at least two semesters in the CS core, you know at least one programming language. You may know two, or be learning a second, from Intermediate Computing. If you use Linux and write shell scripts, you know another. You may have learned a language or two from your job. From noodling on the web, or working on personal projects, you may know some others, or at least know about them. With all this experience, you probably have gut feelings about these issues. I hope that this course gives you more and better tools for understanding and forming your intuitions about programming languages.
Toward a Science of Programming Languages
Science and Computer Science
Where does this need to classify languages come from? One strong influence: a misguided sense of how to make Computer Science a science.
Scientists draw boxes! They do more, of course, but categorizing is a big part of science. Categories are one of the ways that we record our understanding of the things we see and find.
Consider these three scientists:
|
|
|
The first is Carl Linnaeus. He formalized binomial nomenclature, the modern system of naming biological organisms. When we say E. coli or Homo sapiens, we use Linnaeus's naming system. His taxonomy enabled biologists to categorize living things in a consistent way.
The second is John Dalton, who introduced the atomic theory in chemistry. Look around at the bewildering amount of stuff in the world. Atomic theory outlines the building blocks that make up everything.
The third is Erwin Chargaff, whose experiments solved the base pair problem in DNA, even though he never expressed his results in this way. Chargaff gave us the rules of composition for DNA, creating a grammar of biology.
Scientists create taxonomies, theories of building blocks, and rules of composition in order to express our understanding of the world. Computer scientists have tried to do that for programming languages, too. They have had the best of intentions, but what the results are usually unsatisfying.
The problem: Our boxes are a mishmash of different dimensions. We can't even agree on the atoms.
Consider Python. Is it a procedural language? It has classes, so maybe it is object-oriented. Many people consider it a scripting language, because it is so useful for writing small bits of code that glue other components together. It is interpreted, but can be compiled just-in-time. And on and on.
One of the main goals of this course is to help you develop a scientific mindset about programming languages, a way to think about building blocks and rules of composition that leads to taxonomies that computer scientists and professional programmers alike can find helpful.
I won't ban all words used to name the boxes above, even though that might be a great way to run a course. But we will use them in a more limited sense. Programs written in a language can follow a certain style. Subsets of a language can define or support a certain style. But entire languages of the sort we see in industry usually contains big blobs of features that don't fit into only one box.
Bringing a Scientific Mindset to Programming Languages
How would you use a scientific mindset when someone gives you a new programming language? Say, you know Python and they give you Java, or you know Python and maybe Java and they give you, oh, say, Racket.
First, what do they give you when they "give" you a new programming language? They may say that they are teaching you a new way to think or to write program, but that is rather abstract. In addition, they also usually give you two more concrete things:
- a specification or a grammar: a set of rules
- something that runs: a compiler or interpreter
What do you do then? If you are like most people, you look for examples — and run them!
Then you create your own examples. You start thinking, I wonder what happens if...?
This is the moment you start to learn a new language.
One of the challenges we usually face is that people give us big languages. No one wants to learn a toy language. They want to write a game, or a web server, or an operating system. We want more and bigger and powerful.
The result is a jumble of features.
Even so, in any blob of a language, there is at least one small box that captures its essence: a combination of some building blocks that expresses what you can do and how you can think with a language.
The boxes we drew above are motivated by good intentions and driven by reasonable intuitions, but they are mostly the wrong way to think about programming languages. We want to look for the basic building blocks and the rules for putting them together to make bigger units.
We want to be able to ask a few simple questions of any programming language: Does the language have functions? Are they first-class? Does it have objects? What kind? + Does the language allow mutation? What kind? And so on.
Python, Java, JavaScript, and Racket all have objects — of very different kinds!
In this course, we will learn about some of the basic building blocks of a program and some of the fundamental rules of composition.
Course Details
Welcome to CS 3540, Programming Languages and Paradigms. I am Eugene Wallingford, your instructor for the course.
CS 3540 differs from most other CS courses. It is not a theory course, but it does ask you to step outside the confines of any particular programming language, to consider just what a programming language is and how programs written in such a language can be interpreted and executed. I expect that you will find the course challenging, but I also hope that you find it fascinating and rewarding of your effort.
In class, I pass out a short sheet of "vital statistics" that contains basic contact information for me and the course. It is the first page of the syllabus. The most important piece of data on that sheet is all you need: the URL of the course home page:
https://www.cs.uni.edu/~wallingf/teaching/cs3540/
The course web site includes links to:
- the course syllabus
- all the materials you'll need for the course, including session notes, homework assignments, and quizzes
- programming material and other resources for the course
These materials are organized within a rough schedule for the semester, including tentative dates for three quizzes. Keep this sheet with you at all times. Set a bookmark or open a tab on the web page in your browser. You never know when the urge to study Programming Languages will strike you!
Every session page will have a table of contents at the beginning and a wrap-up at the end. After Session 1, most will have a section near the beginning named "Where Are We?" or something similar. It reviews key ideas from recent sessions and sets the stage for the day.
Be sure to take advantage of the elements on the pages. The Table of Contents toggles open and closed. The links are blue. There are a variety of information boxes, quotations, and instructions. There are even footnotes embedded in the text.
Study the course syllabus carefully. It lists the policies by which we will run this course. You will need to know these policies and when they apply.
Some points to which you should pay special attention:
- I post almost everything I say, write, and do in class on the course web site. In particular, notice that I post lecture notes and homework assignments on the home page.
-
We have a course mailing list,
cs-3540-01-spring@uni.edu,
through which we can discuss course topics, ask and answer
questions, and so on. By default, you are subscribed to
this listserv from your
uni.edue-mail address. If you intend to send mail from some other address, let me know. - The material I assign for you to read comes primarily from a language guide and a language reference that are available online. The rest will come from other texts or pages on the web.
- Late work is not accepted for grading — unless you and I make arrangements in advance. Please contact me if you need to make a special arrangement. I will try to help if I can.
- I encourage collaboration on homework but also take very seriously the issue of academic honesty. You may share ideas, but you may never share code.
One thing not on the syllabus that you will learn soon is that you will submit programming assignments online, with only occasional hard copy.
As I said earlier, this course is likely different from other CS courses you have taken. I think you'll find that it requires a steady effort throughout the semester. But I think that you will find that your effort is adequately reflected in your grade. Warning: You will want to complete all of the assignments — and understand them as well as possible — if you expect to pass the course and earn a desirable grade.
And now for the name of the course...
"Programming Languages ..."
TL;DR: In this course, we learn only one "real" programming language, as tool for studying the building blocks of programming languages. This will help you learn other languages later.
Coming here today, you may not have a very good idea of what this course is all about. You shouldn't feel bad.
To this point in your CS education, we have largely confronted you with lots of specifics: how to write programs in a specific language, how to use and implement specific data structures, and how a specific computer executes machine-level instructions. The language has been a tool. Even when we have tried to emphasize issues that are more abstract, your attention has usually been firmly focused on details. This course tries to change that.
Coming here today, you may think of a programming language as nothing more than "something you use to write computer programs". That is true, but circular. It doesn't shed much light on why Python and Java exist, or why they are the way they are. Thinking about languages in terms of the programs we can write is pretty handy in a world that enables us to earn a living writing programs. But that view limits our thinking — and sometimes limits the living we can earn by writing programs.
One definition of "programming language" I find useful is from Abelson and Sussman :
A programming language is a framework for organizing ideas about processes.
When you study computer science, you are learning more than vocational skills. CS is also a discipline that explores a set of big ideas that swirl around representation, computation, and process. It gives us tools for talking about ideas we had a hard time even expressing before.
We write computer programs for a lot of reasons: to solve a problem, to understand some part of the world better, to make money. Whatever the reason, we eventually want to be able to execute the program and see a result.
Other disciplines also build models to help them understand the world. What makes CS different is that we can run our models: they are alive when executed on a computer!
In this course, we will study a few important concepts of programming languages by reading and writing language processors that expose individual concepts.
"... and Paradigms" — Um, What?
TL;DR: A programming paradigm is what I called a "style" earlier. The procedural programming you learn in the intro course is a style. Object-oriented programming is a style. Functional programming is a style. They are not incompatible with one another. You can learn and use all of them (and more).
The Origin
What about the second part of the course name, paradigm? The dictionary definition of the word includes:
- paradigm
- 1 : a model for something that may be copied : EXAMPLE, PATTERN
- 2 : a philosophical and theoretical framework of a scientific school or discipline within which theories, laws, and generalizations, and the experiments performed in support of them, are formulated
The first definition refers to a pattern for something that can be copied. The third refers to a theory about how something should be done or thought about.
The third definition is the one most people mean these days when they use the word, especially in business and science. In this sense, a programming paradigm is a theoretical framework within which we think about and write programs. Different theories provide different ways of thinking about computations and thus give rise to programs of different form.
This is the usage of 'paradigm' that became popular in the worlds of business and science several decades ago, and it filtered into computer science.
Actually, though, the first definition is a better way for us to think about different kinds of programming. A paradigm is a pattern or example of how to program.
Another way to think about paradigms of programming languages is to think of human languages relate to one another.
If you are a fluent English speaker, which is easier to learn: German or Mandarin? Probably German, because it is more similar to English than Mandarin. German comes from the same framework, the same "family" of languages, as English.
The same is true of programming languages. If you are a fluent programmer of Python, then it may be easier to learn C than, say, Smalltalk. This is not because Smalltalk is harder to learn in its own right, but because it is a different kind of language. A Java programmer may find learning Smalltalk a bit easier, despite the fact that Java and C look very much alike — much more so than Python resembles C — because Java and Smalltalk are alike in some very important ways. They are members of the same language family.
Programming languages resemble human languages in another respect, too. The environment and history of a group of people help to create its culture, and the language that a group of people uses both shapes the culture and comes to reflect the culture, and thus its environment and history. Much of what we mean when we say "programming paradigm" is a reflection of programming culture.
A Second Goal for the Course: Another Style
TL;DR: This semester, you will learn to program in a functional style using the Racket programming language. It may seem strange at first, because it is different from what you are used to. But it offers advantages that make it worth the effort.
You have all written programs that include and use functions. Here is a simple example in Python:
def square(x):
return x * x
Of course, we also write code that looks like this:
def processNext():
message = InboxQueue.popMessage()
if message:
process(message)
processNext doesn't return a value, so it's
not really a function at all. We might call it a
"procedure".
But wait: there's another issue. According to the function
header, processNext takes zero arguments. But
notice that it refers to a value from outside the code:
InboxQueue. That means processNext
depends on the state of the world outside the code.
InboxQueue is a hidden input to the
function. Even more, processNext seems to
change the state of the world outside the code when it pops
a message from InboxQueue.
Functional programming is a style of programming in which functions receive data as input, process only that data, and return a value. The word "only" is the key.
In functional programming, programmers abstain from two habits common in other styles:
- mutating data, that is, changing the value of a variable rather than passing a value, and
- relying on external state, that is, referring to values that are not provided as inputs to a function, including global variables.
Without state and mutation, the behavior of each function is self-contained: we don't need to look anywhere else to determine what it does and how it works. As a result, it is easier to prove things about the function's behavior. Computer scientists often want to do that. It is also easier to reason about the function and to test it, which programmers need to do as a part of their jobs.
In this course, we want to write programs that analyze other programs, and using a functional style for the inputs makes them easier to process.
Programming with functions isn't really new to you, but programming in a functional style requires a new kind of discipline. It may feel uncomfortable for a while, but you'll be surprised how easy the style feels to you after a few weeks of practice.
This semester, you will program in Racket, a language that makes functional style a more obvious choice. It may seem strange at first, too, because it is different than what you are used to. But it, too, will become familiar over time. And you will find that it is a language perfectly suited to developing a scientific mindset about programming languages.
One of the goals of the course is to help you become familiar with the functional style of programming, to broaden your idea of what a programming language can be, and to broaden your idea of what programming itself can be.
Make a good faith effort to learn Racket, and you will be rewarded many-fold. Just imagine what the world would have been like if folks had shied away from learning to fly airplanes because they were so different from driving trains and automobiles?
Wrap Up
Reading
Browse the course web site, in particular the syllabus.
Browse these short opening sections of The Racket Guide:
- Chapter 1
- Section 2.1
- Section 2.2 through the end of 2.2.6
When you see "2.2.7 Anonymous Functions with lambda", stop. The reading gets a bit too deep for us starting there. We'll continue there later when we have more background.
If you have time, review these lecture notes, which have a bit more detail than what we discussed in class. If you would like to see my answers to the survey questions, check them out!
Homework
Homework 0 is available and due at the beginning of our next class, 12:30 PM on January 22. As the assignment says, bring hard copy of your write-up to class next time. There is no electronic submission for this assignment.
Computing
Begin to learn about the tools you will use to program in Racket this semester. If you have extra time and are eager to start, download Dr. Racket and begin to explore. You are under no obligation to do so! We will begin our study of Racket next session.