Chapter 6 — Teaching Notes

One-line purpose. Turn students' straight-line programs into decomposed, procedure-based software, and drill the two habits that define robust Fortran: an intent on every argument, and arrays passed as assumed-shape.

Key ideas to emphasize

  • intent is the star. This is the chapter's genuinely distinctive idea — a compiler-enforced contract most languages lack. Make it visceral: show the compiler rejecting an assignment to an intent(in) argument live. Students who leave writing an intent on every argument out of reflex have gotten the whole chapter's value.
  • Function vs subroutine falls out of data flow. Resist letting it become a style preference. "Returns one value, no side effects" → function; "acts on state / returns several" → subroutine. Case Study 1 is built entirely on making students derive the boundary rather than memorize it.
  • pure/elemental are optimization licenses, not decoration. Tie them directly to Ch. 27/33: the keyword is a promise, and the promise is what lets the compiler vectorize and parallelize. The "compute to_kelvin(t) once outside the loop" example in §6.4 is the concrete hook.
  • Assumed-shape is almost always right. The size travels with the array; you never pass n. Contrast hard with legacy a(*), which hides the extent and defeats bounds checking.
  • Explicit interface is the hidden thread. Optional, keyword, and assumed-shape all require it — which is why we put procedures in contains (and, in Ch. 8, modules). Name this connection explicitly.

Misconceptions to preempt

  • "intent(out) preserves the incoming value." (No — it arrives undefined; use inout to keep it. The accumulator bug in Exercise 6.9 is the canonical trap.)
  • "A function can return several values like a Python tuple." (No — one result; use a subroutine.)
  • "I can read an optional argument's value whether or not it was passed." (No — guard with present.)
  • "elemental means the argument is an array." (No — the argument is scalar; the language fans it out.)
  • "Assumed-shape keeps my array's 0-based bounds." (No — the dummy renumbers from 1 unless you write a(0:).)
  • "Recursion is the elegant, therefore better, choice." (In numerical kernels iteration wins — no stack risk, no call overhead.)

A live demonstration (5–8 minutes)

  1. Compile the swap program from §6.2 — it works. Then change the arguments to intent(in) and recompile; read the error aloud. Students see the contract enforced. Then fix it back to inout.
  2. Paste an elemental to_kelvin into Compiler Explorer (gfortran), apply it to a scalar and to an array, and note that the single definition serves both. Optional: show the vectorized loop the compiler emits.

Class-time budget (~50 min)

  • 8 min: subroutine vs function; the result clause; the data-flow rule (§6.1).
  • 12 min: intent — the three intents, the compiler enforcing them, the out-wipes-value trap (§6.2).
  • 8 min: optional + keyword arguments; present (§6.3).
  • 8 min: pure/elemental and the optimizer connection (§6.4).
  • 6 min: internal procedures, explicit interface, recursion-vs-iteration (§6.5).
  • 8 min: assumed-shape vs explicit-shape vs assumed-size; the Project Checkpoint step (§6.6 + project).

Prerequisites to review

Chapter 5 (arrays, sections, whole-array ops, allocatable, column-major) is essential — the array-argument material and the step refactor lean on it directly. Confirm students are fluent with size, array sections like a(2:n-1), and allocate before this chapter.

Connections

Back: Ch. 4 (control flow — the loops inside procedures), Ch. 5 (arrays). Forward: Ch. 7 (I/O, next), Ch. 8 (modules — where these procedures move and get explicit interfaces for free), Ch. 9 (field_t type in step), Ch. 27 (the pure/elemental optimization payoff), Ch. 33 (parallelizing the pure update). The step interface designed here is stable for the rest of the book.