Welcome to the course!
pdf
's are created by
exporting the Org files to LaTeX.?
to see a help page describing the possible interactions.esc
or o
to see an overview of the slide deck.Emacs is
An extensible, customizable, free/libre text editor — and more.
At its core is an interpreter for Emacs Lisp, a dialect of the Lisp programming language with extensions to support text editing.
— GNU Emacs homepage
Even if you do not use Emacs, I recommend checking out Org mode.
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
— Org mode homepage
While Org mode is used in plain-text documents, it supports
exporting to various formats, including pdf
's (through LaTeX),
html
, and odt
, all “out of the box”!
Packages for Org mode are available for both VSCode and Atom.
Org mode is especially useful in that it provides support for literate programming.
Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
— Donald E. Knuth, “Literate Programming”
Regardless of the tools you choose to use, in this course it will be expected that you follow this philosphy.
That is, documentation is not optional, and not to be an afterthought.
The undergraduate calendar description of this course is
Design space of programming languages; abstraction and modularization concepts and mechanisms; programming in non-procedural (functional and logic) paradigms; introduction to programming language semantics.
But we should be more specific.
Before beginning this course:
After completion of this course:
Topic | Below | Marginal | Meets | Exceeds |
Familiarity with various programming languages (PLs) |
Shows some competence in procedural languages, but not languages from other paradigms |
Shows competence in procedural languages and limited competence in languages from other paradigms |
Achieves competence with the basic usage of various languages |
Achieves competence with intermediate usage of various languages |
Ability to identify and make use of abstraction, modularisation constructs |
Cannot consistently identify such constructs |
Identifies such constructs, but does not consistently make use of them when programming |
Identifies such constructs and shows some ability to make use of them when programming |
Identifies sucj constructs and shows mastery of them when programming |
Ability to comprehend and produce formal descriptions of PL syntax |
Unable or rarely able to comprehend given grammars; does not identify ambiguity or precedence rules |
Comprehends given grammars, but produces grammars which are ambiguous or which do not correctly specify precedence |
Makes only minor errors regarding precedence or ambiguity when reading or producing grammars |
Consistently fully understands given grammars and produces correct grammars. |
Ability to comprehend and produce operational semantics for simple PLs |
Rarely or never comprehends such semantic descriptions |
Usually comprehends such semantic descriptions, but cannot consistently produce them |
Comprehends such semantic descriptions and produces them with only minor errors |
Comprehends such semantic descriptions and produces them without errors |
Ability to comprehend denotational and axiomatic semantics for simple PLs |
Rarely or never comprehends such semantic descriptions |
Inconsistently comprehends such semantic descriptions |
Consistently comprehends such semantic descriptions |
Consistently comprehends and can produce some simple semantic descriptions |
Before we begin in earnest, let us set the stage by answering some basic questions.
Languages can be distinguished by two components:
Change either, and you have a different language.
Sometimes implementation strategy is also considered a component of a programming language.
We do not take this view.
Classifications of programming languages based on what kind of abstractions they (natively) support.
It is common to consider only a small number of paradigms, usually in this hierachy.
Imperative/Procedural | Declarative | ||
Object-oriented | Non-Object Oriented | Functional | Logic |
But this is far from a complete picture!
![]()
— Van Roy, P. “Programming Paradigms for Dummies: What Every Programmer Should Know”
Different paradigms lend themselves to different tasks, so it is beneficial for a language to support more than one.
But then, “More is not better (or worse), just different”!
All computation models have their place. It is not true that models with more concepts are better or worse. This is because a new concept is like a two-edged sword. Adding a concept to a computation model introduces new forms of expression, making some programs simpler, but it also makes reasoning about programs harder.
Pick a language you are familiar with, and research what paradigms it supports. (Don't expect to find a definite yes/no answer for every paradigm from Van Roy's taxonomy).
Then try to determine paradigms which are not natively supported, but are still feasible to follow when coding.
We can use a mixture of objective and subjective criteria to compare and evaluate languages we discuss.
We use four main subjective criteria. Note there is overlap!
The last two points deal with orthogonality.
Orthogonality in a programming language means that a relatively small set of primitive constructs can be combined in a relatively small number of ways to build the control and data structures of the language.
— Concepts of Programming Languages 10th ed.
Following are some key concepts and terms which
(Some of this information simply won't have a better place to go).
Languages exist in a hierarchy.
Translate the whole program (and any libraries or other code resources needed) ahead of running it.
Translate the program as we are running it.
Compile into an intermediate language, which is then translated into assembly.
Research for yourself what implementations are available for languages you are familiar with.
Consider:
The concept of an abstraction is central to programming languages.
We define an abstraction loosely as a tool or device that solves a particular problem.
— Concepts, Techniques, and Models of Computer Programming
Briefly, abstraction means the ability to define and then use complicated structures or operations in ways that allow many of the details to be ignored.
— Concepts of Programming Languages 10th ed.
Highly abstract (User knows fewer details) |
A writing instrument ↓ A pencil ↓ A mechanical pencil ↓ This pencil |
Highly concrete (User knows all details) |
Language A
is “higher-level” than language B
if it allows you
to work at a higher level of abstraction than language B
.
We will see these terms in particular applied to many concepts.
The scope of an entity is the portion of the program in which it is “visible”.
A scope is a portion of the program to which the visibility of entities may be limited.
Try out this snippet of Emacs lisp code, either in Emacs or using an online REPL.
(let ((x 2) (y 5)) ; "global" variables x and y
(progn
(defun mult-x-y ()
(* x y)) ; returns x * y
(defun A ()
(let ((x 3)) ; local variable x
(mult-x-y)))
(defun B ()
(let ((y 10)) ; local variable y
(A)))
(message "mult-x-y returns %d, A returns %d and B returns %d"
(mult-x-y) (A) (B))))
In a few different programming languages, investigate whether condition branches and loop bodies introduce scopes.
I.e., test out code such as
if B then
int x = 0
endif
y = x % Is x still in scope?
Specifically, investigate languages which have iterating loops,
(usually called for
loops). What is the scope of an iterator
for such loops?
In the context of running a program (or a thread of a program):
We can distinguish four kinds of memory allocation.
malloc
or new
.Investigate:
The lifetime of a variable is the portion of the runtime (not the code) during which it has memory allocated for it.
Garbage: allocated memory which is no longer accessible.
Garbage collection: deallocating garbage.