In this lecture, we introduced the field of programming language theory, the study of the design, implementation, and analysis of programming languages.
First, we discussed the topics of syntax and semantics, being what programs are and what programs mean. We saw that we could define simple grammars defining the syntax of SML programs, and introduced the concept of judgements, which are how we notate and communicate the semantics of programs.
We saw examples of judgements which defined the static and dynamic judgements of a simple expression language, those being the typing rules which determine valid expressions and evaluation rules which dictate how to simplify expressions. We saw that due to our inductively defined rules, we were able to do induction to prove properties about our language that we would want to be assured of.
We then introduced the (untyped) lambda calculus as the simplest example of a programming language, consisting only of lambda expressions, variables, and applications of functions, which nevertheless remains capable of computing any general function. We saw that this was possible through the Y combinator, which let us define recursion in terms of nothing but function application and substitution.
We worked through an example where we implemented the fact function with nothing but lambda terms. While this is powerful, the lack of types made it hard for us to reason about lambda terms. We saw that another way to phrase the lambda calculus is through the simply-typed lambda calculus, which is the core language within any strongly typed language.
We finished with a brief note on the fact that while the simply typed lambda calculus is simple and inexpressive, the study of type theory allows us to add "widgets" in the form of more exotic types and terms to it, which eventually converges on all the modern programming-day language features which we would want. Through this way, we can understand every modern programming language as a kind of extended lambda calculus.