Programming Languages: Application and Interpretation
The main site for Programming Languages: Application and Interpretation by Shriram Krishnamurthi. The language environment is Racket, so it's useful to refer to the Racket Guide every now and then.
The PLAI language is included with DrRacket so there is no reason to install it.
Two cultures of pedagogy:
- Interpreters. Writes programs to learn concepts, using the fundamental belief that by teaching the computer to execute a concept we more thoroughly learn it ourselves.
- Survey of Languages. Helps us understand the bigger consequences, and its impact, rather than just the definition.
People tend to learn better through induction (specific to general) rather than deducation (general to specific). 
Some other resources that are helpful when working through this text, since all of the programming for the text is done using Scheme:
- The Little Schemer
- How to Design Programs
- Teach Yourself Scheme in Fixnum Days
- Uniprocessor Garbage Collection Techniques
- Model checking
- Syntax is mostly a distraction.
- Idioms tell us more about the programmer than the language.
- Distinction between intrinsic primitive and potentially superfluous library operation can be made rigorously using mathematics.
- Really what we want to study is semantics, or the behavior that is associated with the syntax.
English is a terrible and imprecise way of capturing the meaning of a program, and mathematics is more precise. We traditionally have three mathematical semantics:
These are either too advanced or too cumbersome to use, so we use interpreter semantics (a first cousin of operational semantics) instead. The idea is simple: to explain a language, write an interpreter for it.
A parsing translates concrete syntax into abstract syntax.
The read primitive is the crown jewel of Scheme and Lisp. This is why so many languages built atop Lisp and Scheme look so much like it. It reduces the elaborate tasks of tokenizing and parsing into three phases: tokenizing, reading, and parsing. The read primitive does the first and the second.
You can write programs that consume programs (interpreter), or write programs that produce programs (compiler).
An identifier names the value of an expression. We avoid the term variable as it is semantically charged; it implies that the value associated with the identifier can change. Strings can be used for identifiers, but symbols are better: they have the property that they can be compared in constant time.