Last modified: 2026-10-28 01:12:24 (PDT)
AI-Assisted Authorship
This chapter was written with the assistance of GitHub Copilot, which expanded on outlined ideas and draft notes provided by the author. The content represents the author’s perspective and has been reviewed for accuracy, but the detailed prose was generated through AI assistance.
Lecture notes, slides, and problem sets teach rather than report. The general rules for scientific writing in the other chapters still apply. This chapter adds the rules that apply to teaching materials in particular.
Active learning, in which students work through tasks themselves during class, improves exam performance over lecture alone (Freeman et al. 2014). The exercise-first structure is this guide’s own convention for putting that result into practice. Pose each task as an exercise, give students time to try it, and then show the solution.
#def- or #thm- div follows the solution div.#exr- div and its own #sol- div, in order, rather than one exercise with parts (a) through (e). Any exercise with several parts is split, however the parts are marked: letters, numbers or bullets. Put the shared setup in the first exercise, and begin each later exercise by citing it, as in “Make the assumptions of the first exercise.” Later exercises can use earlier results through cross-references.sol- in place of exr-.Example 1 (Asking before defining)
❌ Generalization is the ability of a model to perform well on new data.
✅
The revised version lets students attempt the idea before they see the formal definition.
Make every unit of analysis as concise and minimal as possible. The units are mathematical expressions and divs of every kind: definitions, theorems, lemmas, corollaries, examples, remarks and proofs. When a unit grows complicated, do not write the complexity into it. Abstract the complexity out into smaller, atomic definitions, results and expressions, each with its own name and identifier, and glue the pieces together with hyperlinks.
This is the compositional approach of modular programming: a program is built from small, single-purpose modules that call one another, and a maintainer changes one module without reading the rest. The notes work the same way. A theorem links to the definitions it uses, a proof links to the lemmas it uses, and an expression is written with the named pieces it is built from.
When a unit still looks long, ask what could be named and moved out.
Example 2 (Splitting one long definition)
❌ One div defines the ridge estimator, defines its penalty, and proves that it shrinks the coefficients.
✅ Three divs: a definition of the penalty, a definition of the ridge estimator that links to the penalty, and a theorem on shrinkage that links to both.
The ✅ version lets a later chapter link to the penalty alone, and each piece fits on a slide.
Defining terms clearly covers what a good definition contains. For teaching materials, four further rules keep definitions findable.
#def- div. A bolded keyword usually marks an inline definition.#def- div. A term defined inside another term’s div, or two terms joined in one title (“Regression and classification”), has no identifier of its own, so nothing can link to it.#def-, #thm-, #lem-, #cor-, #prp-, #cnj-, #exm-, #rem-, #exr-, and #sol-. A special case, such as a linear evaluation function, gets its own div after the general case, and the two link to each other.#def- div. Put the properties of the defined object, such as the symmetry and idempotence of a matrix, in a separate #thm-, #lem- or #prp- div after it, with a proof where one is known. Each abstract div then gets its own example, as the rule below requires.Every alternative name for the same concept stays in the div of the term it names and is treated like the primary name: it appears in the div title and is bold where it first appears in the definition. Name synonyms and near-synonyms where the term is defined, and say which one the notes use. A student who encounters one name here and another in a textbook cannot tell whether the difference matters. For a near-synonym, name the seam: critical points include the stationary points and also the points where the derivative does not exist.
When a symbol or convention has more than one common form, state the one the notes use and name the others a reader will encounter elsewhere. Put the alternatives in the definition div or in a callout beside it. For example, some sources include 0 in the natural numbers and others exclude it, so write \(\mathbb{N}_0\) or \(\mathbb{N}^+\) to make the choice explicit.
Define a quantity in the form that needs the fewest symbols, and state the textbook form as a theorem that follows. For example, define variance as the mean squared deviation \(\operatorname{E}\left[\operatorname{devn}(X)^2\right]\), where \(\operatorname{devn}(X) = X - \operatorname{E}[X]\), and then prove that it equals \(\operatorname{E}[X^2] - (\operatorname{E}[X])^2\).
Parsimony outranks convention when choosing a primary definition. The conventional form still appears in the notes, as a named result.
When several courses or repositories have already written the same definition, theorem, or exercise, compare the versions on notation, decomposition, parsimony, and clarity. Use the best one, or merge them, and make it the single copy. Other places include or link to that copy instead of keeping a second wording that can drift.
Example 3 (Showing the data at first mention)
❌ Slides 3 to 9 discuss the spam data’s 57 predictors, its class imbalance and the loss we will minimize. Slide 10 shows a table of the first rows.
✅ Slide 3 introduces the spam data and shows a table of its first rows and a plot of one predictor by class. Slides 4 to 10 discuss the predictors, the class imbalance and the loss, and refer back to that table and plot.
The ✅ version lets every later slide refer to something the reader has already seen.
This rule applies to all teaching materials, in every course and every teaching repository.
resources: when the site publishes it.#exm- div. The rule covers each #def-, #thm-, #lem-, #cor- and similar div. The example of a related result does not exempt a definition: a theorem that uses a definition gets its own example, and so does the definition. The ai-config rule links here.#exm- div a figure of its data, model or results (Ezra, 2026-10-23). When an example has no figure, state the reason in that div. Put the figure inside the div, or include a subfile whose name ends in _fig inside the div. When an example has nothing to plot, such as a single number, add <!-- no-figure: reason --> inside the div, replacing reason with why there is nothing to plot. The check-exm-figures workflow in gha reports, in a pull request, each example that has no figure and no no-figure comment (gha#1193).check-visualization-figures workflow in gha reports, in a pull request, each such div that has no figure in it or in its solution, and a <!-- no-figure: reason --> comment inside the div suppresses that report, as it does for an example (gha#1262).Reading a worked example is passive. A reader who has just seen one method applied learns more by applying it to a new case than by reading a second example. So each example gets a practice exercise, with its solution, right after it.
#exm- div, add an #exr- div that asks the reader to do the same thing for a different case, followed by its #sol- div. The exercise changes the data, the function or the question, so the solution is not a copy of the example.Example 4 (An example followed by a practice exercise)
✅
The example shows the method once. The exercise asks the reader to repeat it on a new variable before moving on, and the solution’s numbers still come from running code (see Use real data and compute every number).
These rules apply to all teaching materials, in every course and every teaching repository, not only to one course.
group="language". Start a new tabset whenever prose or a new step sits between code chunks, so the reader sees one step’s code in one language at a time. The shared group makes one choice of language apply to every tabset on the page, as long as the tab headings use identical text in every tabset, such as always “R” and “Python”.statsmodels’ sm.OLS, as ISLP_labs does. If an exercise departs from the book, say why in the lab.github.com link into a private repository, or to “the copy in this repository”. Link a data file from the published site, from a public repository or package, or from the data’s original public source.This rule applies to every executed code chunk in teaching materials, in every course and every teaching repository, in every language.
#| include: false. When the chunk that computes those values is already hidden, merge the storing code into that chunk.None and shows the chunk as one code block per printed value, such as a <matplotlib.lines.Line2D object at 0x...> line after every ax.plot(...). End each such call with a semicolon, or assign its value.This rule applies to all R code in teaching materials, in every course and every teaching repository.
lm() or glm(), show its results with modern packages, not with base R output.parameters() |> print_md()) or gtsummary (tbl_regression()), not with summary() or coef(summary()) printouts.plot(), lines() and abline().check_model() for diagnostic plots.model_performance() or broom’s glance().This rule applies to all R code in teaching materials, in every course and every teaching repository.
select(), not with df[, c("a", "b")] or df[c("a", "b")].filter(), not with df[df$x > 0, ] or subset().mutate(), not with df$new <- ....drop_na(), not with df[complete.cases(df), ].bind_rows(), not with rbind().tibble(), not with data.frame().|>.tibble(x, y) |> pander(), not pander(tibble(x, y)), and sizes |> lapply(f) |> bind_rows(), not bind_rows(lapply(sizes, f)). Give a call that would sit inside an argument, such as data = filter(df, train) in a model call, a name on its own line first.This rule applies to code that appears in more than one place in teaching materials.
filters: [include-code-files] to the front matter, then write a code block with an include attribute, such as ```{.python include="script.py"}.start-line and end-line, to show part of a file. Prefer a range that names the lines you want over a copy of those lines.quarto add quarto-ext/include-code-files, and commit the _extensions directory it creates.This rule applies to all reader-facing code in teaching materials, in every course and every teaching repository, in every language.
# add 1 to x above x <- x + 1, gives the what without the why. Say what the step accomplishes and why the analysis needs it, for example # center age so the intercept is the mean outcome at the average age.code-fold by what the code does and whether the prose mentions itThis rule applies to every executed code chunk in teaching materials, in every course and every teaching repository.
Set #| code-fold: on each chunk by two questions: does the prose mention the code, and does the code produce output outside the chunk, such as a figure, a table, or variables that inline expressions use?
#| code-fold: show when the prose mentions the code and the code produces output outside the chunk: a figure, a table, or variables that inline expressions use. The code starts open, and a reader who wants to focus on the output can hide it.#| code-fold: true when the prose does not mention the code. This holds whether the code produces output outside the chunk or no output at all. The code starts hidden, and a reader who wants it can open it.#| code-fold: false when the prose mentions the code and the code produces no output, or only output that the chunk renders inside itself. The code and its output stay together, with no toggle.For example, a chunk that fits a model the text walks through and prints its coefficients is false, a chunk that draws a figure the text discusses is show, and a chunk that loads a package or builds an object that later chunks use is true.
This rule applies to all teaching materials that run code, in every course and every teaching repository.
#fig- div with a caption.ariaLabel.echo: false on a cell you want students to read.#exm- div.#exm- div and short commentary in a #rem- div, because a ::: notes div is plain text without a box on the web page.::: {#rem-name .remark .notes}. Reveal.js shows it only in speaker view, so the audience does not have to read it, and the web page shows it as a boxed remark. Readers who did not attend the lecture use the web page, so nothing is lost, and nothing is said twice. Give a long paragraph a separate short #rem- div only when the slide needs a takeaway to look at.A note sheet is a reference table of formulas with brief labels and no prose. This is one case of building every unit from smaller atomic units. Give each concept its own row. A row holds one formula and one short label.
The same rule applies to every other reference table, such as a table of notation.
Example 5 (Splitting a merged row)
❌ Row:
Dot product, sample mean, with both formulas in one cell.✅ Rows:
Dot productwith its formula, thenSample meanwith its formula.
The ❌ row makes the reader find where one concept ends and the next begins. The ✅ rows let the reader find one formula by one label.
When a term is defined on another page or in another site, state the idea in the sentence and link the term. Do not write about where the definition lives.
Students read concepts, not the structure of the site. A sentence about which notes define a term adds no content, and it goes stale when the definition moves.
Structure the rubric for most STEM questions as a checklist (Ezra, 2026-10-26). A grader then marks each item as earned or not, and the points are the sum of the earned items. A rubric written as a paragraph makes the grader reconstruct the items, and two graders reconstruct different items.
Example 6 (A rubric as a checklist)
❌ Grading (6 points): two for \(\vec r\), one for \(\dprod{\vx}{\vec r} = 0\), three for “orthogonal” with its link to the normal equation.
✅
The checklist shows the grader each item to mark and lets a script check that the points sum to the total.
.callout-note titled “Source”, not in running prose. Adapting another course’s material gives the details, including when a ::: notes div is a safe alternative.These rules from the other chapters apply to teaching materials as to any other writing:
16 Comment every code chunk to say what and why