Final Exam Preparation

The following are questions you should be able to answer, and the study of which should be sufficient to succeed in the final exam. These questions are compiled from previous reading, quizzes, and labs. These items are in no particular order.

Study Guide

  • What are closures? How are they implemented?
  • How do functions and closures relate? Are functions closures? Are closures functions?

Lab 9: Unification & Backtracking

Welcome to the first of two labs on Prolog! Prolog is a language very different from the ones you've seen so far. Don't worry too much about being productive in it. Just try and focus on the ideas from Prolog that we're focusing on. (Of course, if you find it interesting, then by all means dive in deeper than we go in these labs!)

Prolog is a logic programming language, this is a programming paradigm that looks like and works similarly to formal logic.

Before we dive deeper, let's talk a bit about logic.

A Bit of Logic


Lab 8: Object–Oriented Design

In this lab we will be talking about some common and important concepts and patterns in object–oriented design. These are not specific to Java, but we will of course be using Java as the illustrating language.

The SOLID Principle

SOLID is an acronym for five of the most important ideas in object–oriented design:

  • Single Responsibility Principle
  • Open/Closed Principle

Lab 7: Objects & Classes

In this lab we will cover classes, objects, subclassing, composition vs. inheritance, subtype polymorphism, and abstract data types.


This is our first lab with Java, so before anything else, let’s talk a bit about how compilation works in Java.

In Java, you write separate .java files, each of which contains a single class. The name of the file must exactly match the name of the class contained within; so a file called must contain a class called Blah.


Lab 6: Safety & Security

In this lab we will walk through the ways in which Rust’s design facilitates safety, how Rust’s safety guarantees interact with its low-level programming capabilities, and how Rust’s definition of safety interacts with our understanding of security in low-level programming.

Safe Rust vs. Unsafe Rust

Rust is actually split into two languages: Safe Rust and Unsafe Rust. So far in this class we’ve been working with Safe Rust, but in this lab we’re going to get into Unsafe Rust.

The key difference between Safe Rust and Unsafe Rust is that in Safe Rust, the compiler checks your work. It makes sure that nothing you write violates the rules Rust has. In Unsafe Rust, the compiler doesn’t check everything, and instead just assumes you’ve checked the code yourself.


Lab 4: Ownership, Borrowing, & Lifetimes

In today's lab we will introduce the Rust programming language, and the core ideas Rust uses to ensure memory safety without manual memory management or garbage collection. These core ideas are ownership, borrowing, and lifetimes.

Today's lab will be accompanied by copious examples in person, so be sure to show up on time and follow along as we work through them.


Lab 3: Macros

Welcome to the final Racket lab. In this lab, we will be discussing macros, specifically:

  • Quoting
  • Unquoting
  • Quasiquoting
  • Pattern-Based Macros
  • Procedural Macros
  • Homoiconicity

Lab 2: Functions

In this lab, we will discuss functions, the core of functional programming. In particular, we will explore the ideas of anonymous functions (also called lambdas), currying, partial application, and higher-order functions.

Anonymous Functions

Functions do not have to have names. Functions that don't have names are unsurprisingly called "anonymous functions." You may also seem them called "lambdas," which comes from the lambda calculus, a fundamental model of computing.


Lab 1

Lab 1 is intended to give you time to familiarize yourself with Racket.

For your assignment, complete the "Do Now" problem from the end of [chapter 1 of PLAI][c1]:

What happens if you mis-apply functions to the wrong kinds of values? For instance, what if you give the caml constructor a string? What if you send a number into each version of good? above?

View sudoku-loeb.hs
import Data.List
-- This code solves Sudoku puzzles using a magical function called Loeb.
-- Loeb allows you to define a list of functions which resolves into a list
-- of values, allowing the list to self-reference. In the case of Sudoku, the
-- solver code will terminate only in the case where the Sudoku puzzle has
-- a unique solution.
-- The code starts with a 1-dimensional list (representing the 2-dimensional