63 Calculus lessons
| (require animate/calculus) | package: animate |
This module declares immutable single-variable calculus lessons. It is a headless semantic API: importing it does not create a Pict, access a font, open a window, or write a frame. Native conversion is in animate/calculus/render.
syntax
(define-calculus-model model-id (model [name expression] ...) maybe-constraints)
syntax
(define-calculus-lesson lesson-id (model [name expression] ...) (views [view-name view-expression] ...) clause ... (step step-id step-option ... command ...))
63.1 Caption text
A step may supply #:say ordinary display text. Strings use the shared inline-TeX grammar: $...$ and \(...\) are inline mathematics, while $$...$$ and \[...\] are display mathematics. Write \$ for a literal dollar sign. The headless calculus plan retains caption source without loading TeX; parsing and the formula backend run only in prepare-calculus-plan. The prepared caption is reused by Pict, Visual, and Scene sampling, so a frame never initiates TeX typesetting or caption reflow.
For literal source or a programmatic plain-text fallback, require animate/text-content and supply inline-text, tex-span, or literal-text as the #:say value. Ordinary string captions still inspect as their authored string through calculus-plan-caption. Structured values inspect as text-content?. Audio narration, speaker notes, and subtitle export remain plain-text channels; no TeX source is treated as speech automatically.
syntax
(define-calculus-component component-id (inputs [name : type] ...) (model [name expression] ...) (exports name ...) maybe-constraints maybe-exposition)
Within a lesson, (use-component component-expression argument ...) creates one distinct instance and (part instance 'export-name) addresses an export. Private bindings are not public addresses. A collapsed explain reveals public exports. An expanded (explain instance #:mode 'expanded) inserts the component’s lexical steps into the caller timeline, retaining their delays, durations, pauses, and parallel groups. It must be the only command in its enclosing step and cannot be nested in together. During expanded graph exposition, visible private construction leaves use an internal renderer namespace only when they have one unambiguous compatible caller graph view. They remain uninspectable. The local steps have stable paths of the form '(outer-step instance local-step); a local checkpoint appends its checkpoint name. A replay in another outer step therefore creates a distinct timeline occurrence without cloning the component’s mathematical instance. While an expanded local step is current, its #:say caption takes precedence over the outer caption. Default auxiliary cleanup hides private leaves still shown without hiding caller inputs or public exports; the explicit #:auxiliaries 'deemphasize and #:auxiliaries 'keep policies retain them deliberately.
Inside a model and its lesson clauses, the contextual vocabulary includes parameter, domain constructors such as closed, held function and piecewise-function declarations, graph, point-on, input-reading, derivative-function, definite-integral, graph-view, formula-view, and exposition commands such as show, hide, read, vary, approach, together, and checkpoint. These spellings are not exports that change ordinary Racket code outside a declaration. procedure-function receives an opaque provider through (external provider) and an authored #:key. Its declared finite #:breaks are mandatory native graph gaps even when the provider returns a finite value at that input. Provider exceptions and non-finite returns remain explicit partial results rather than unexplained painted holes.
Finite analysis forms preserve source-declared mathematics independently of frame order. (sequence (n) expression #:from first-index) binds an integer index, (partial-sum sequence #:from m #:to n) is inclusive and returns zero when n is smaller than m, and (sequence-points sequence #:through n) represents only discrete indexed samples. iteration-map and newton-iteration compute an inspected prefix from their declared seed; a Newton derivative must be a derivative-function of that iteration’s function. An unavailable update remains a partial result rather than selecting a new seed.
level-set, root-point, and intersection-point validate supplied candidates only; none starts a hidden root search. Sign, monotonicity, concavity, and feature declarations retain supplied scopes, categories, and nonempty justifications. They validate that declaration data, but do not claim to prove an interval theorem from graph samples.
Limit forms preserve a separate limiting context. neighborhood and punctured-neighborhood are open domains with positive authored radii. limit-statement validates its direct real parameter, target, side, and supplied justification without evaluating the source at the target. epsilon-delta-condition requires finite positive epsilon and delta; continuity-condition reports a declared limit/value mismatch as a contradiction rather than treating it as a display preference. asymptote-line likewise requires its supplied line to match the finite/infinite shape and value of its limit claim; no asymptote is inferred from a view boundary. The public input/output-band parts of an epsilon–delta condition evaluate to their finite boundary interval and render as clipped graph-view guides, while the unbounded mathematical band itself remains a semantic region.
Differential constructions retain function provenance: tangent and linearization accept only a derivative-function declared for the same held function. vertical-tangent is a separate supplied claim and requires a nonempty justification rather than a fabricated finite slope. taylor-polynomial uses its supplied ordered compatible derivatives; an empty derivative list produces the constant approximation at its base. approximation-error remains signed, while error-segment joins the two exact graph values at its authored input rather than measuring a screen distance. slope-triangle derives its directed horizontal and vertical legs, including signed dx and dy, from an increment or a nonvertical line and an authored run. Finite geometric extents are retained: segment and chord evaluate as their authored endpoints (including a coincident zero-length chord), ray-through keeps its origin and direction, and secant remains an infinite line. Native graph rendering clips only infinite extents to the active view; it does not turn a chord into a secant. slope also accepts a nonvertical segment. Visible increments and slope triangles are likewise drawn from their semantic from/to and horizontal/vertical parts, rather than from a screen angle. Visible riemann-rectangles are prepared from the exact partition, tag, and function values in the snapshot. Positive and negative contributions retain their sign when clipped to a graph view. trapezoidal-regions use the same snapshot contract; a cell crossing the x-axis is split at its mathematical affine zero instead of being painted as an unsigned polygon. partition-marks place fixed-size ticks at the resolved exact endpoints on a graph view’s mathematical x-axis. Visible interval-marker spans preserve declared open/closed membership on their selected graph axis, including finite unions, intersections, and holes from domain-except. An approach-marker receives its axis and direction from held semantic data. An endpoint-marker is painted closed after the core verifies an included graph boundary, or open when a transparent held function body supplies its exact excluded-boundary value. An unsupported branch-limit endpoint remains unresolved; native drawing does not invent a circle. region-under, integral-region, and region-between are sampled from their held graph functions, retaining undefined gaps. Areas between crossing graphs split at their mathematical intersection rather than selecting one global upper curve. sequence-points render as isolated index/value markers; no continuous stroke is inferred between integer-indexed sequence values. number-line-view has a native coordinate axis for visible scalar and selected solution markers; it is not treated as a formula panel. Visible sign-chart intervals are drawn only from their supplied signed claims and authored finite domains; the renderer does not sample a graph to establish their signs. Formula views prepare held formula, formula-of, and value-readout rows from semantic references and current snapshot values. In particular, ref keeps symbolic quantity identity while value and readouts display the live value, including approximate-result provenance; formulas are never recovered from opaque descriptor printouts. Rows without an explicit value leaf are resolved once during native preparation and reused across frames. Rows with a value leaf, and readouts, remain snapshot-dependent. Visible newton-diagram objects draw each available finite update as its semantic graph-point-to-next-axis-intercept construction. A failed or unavailable update is not extrapolated by the renderer. Native panel planning respects the selected layout’s deterministic panel order and stacked/side-by-side arrangement. Repeating an object in two views creates two presentations of the same snapshot value, not two animated copies. Use (show (in-view plot G)) or (hide (in-view plot G)) to change only that presentation; show or hide on a declared view name controls its whole presentation container. A calculus-snapshot-visible? query with #:view reports one named presentation, while an unqualified query reports whether the object is visible in any declared view. Labels retain their mathematical anchors while the native adapter assigns a stable candidate slot by label identity. Colliding labels use a bounded clockwise fallback and a leader line rather than moving an anchor or depending on frame request order. For a graph view declared with #:scale 'equal, native preparation letterboxes the declared coordinate window so the two mathematical axes use equal pixels per unit. 'independent continues to use the full panel; neither policy changes a mathematical slope or point coordinate. With #:y 'auto, preparation uses the layout profile’s fixed representative sampling policy to fit finite visible graph/point evidence once over the prepared lesson, then retains that padded vertical window for all still and scene requests. Infinite lines and bands do not create an arbitrary fit, and reversed or sparse frame selection cannot trigger a new one. If no finite fit evidence is available, preparation requires an explicit #:y interval. An asymptote-line is rendered only after its supplied limit claim and line shape have been semantically checked; an unresolved claim does not create a decorative asymptote. Input and coordinate readings share the same snapshot-owned point and guide construction in graph views, so their markers and axes remain mathematically attached under any camera window.
trace accepts a trace-of locus only when it uses one direct real parameter over a closed, finite, increasing interval and that parameter starts at the interval’s left endpoint. An invalid sweep is diagnosed during plan compilation and leaves sampled parameter state unchanged; a preceding set-parameter can establish a valid start. The locus is evaluated from its sweep definition at every sampled state: trace exposes only the prefix through the current sweep coordinate, while show reveals the same locus in full. Undefined points remain mathematical gaps.
Children of together share one pre-group state. The compiler rejects a group whose children write the same parameter, the same persistent presentation property of overlapping targets, or the same view window. A rejected group leaves no partial sampled updates behind.
snapshot-of accepts #:values bindings written as ([parameter constant] ...). It fixes the requested object at those values, while unlisted parameters use the model or lesson’s compiled initial values, including compile-time overrides. It never captures a live rendered frame.
limit-transition requires a matching finite slope-limit claim for two nonvertical lines through the same anchor in a shared graph view. The source must be visible and the distinct target hidden at action start. A valid transition hides the finite source and reveals the target without assigning the limit to the approaching parameter; an invalid transition leaves presentation state unchanged.
focus and restore-view act only on a declared graph view. Focus evaluates and freezes its finite x/y window at action start, then changes only the view’s camera window; it does not mutate graph domains, points, or parameters. In a view with #:y 'auto, the focus track uses the same preparation-time frozen fit as its baseline, without refitting any frame. restore-view returns to the declared or frozen auto-fit initial window.
Profiles are immutable presentation policy. A calculus-theme can inherit a base theme and append ordered calculus-style rules. A rule may select kind, declared role, presentation state, public target address, and view. Each cosmetic property cascades independently; specificity compares view, target, state, role, and kind in that order, and later equal-specificity rules win. A derived theme inherits its base colors and rules.
(define emphasis-profile (calculus-profile #:theme (calculus-theme #:base dark-calculus-theme #:rules (list (calculus-style #:kind 'point #:fill "#79B8FF" #:marker-radius (calculus-px 5)) (calculus-style #:target 'R #:stroke "#79B8FF" #:dash 'solid)))))
Styles may set stroke/fill colors (including alpha), stroke width, dash, opacity, marker radius, and formula font size. They change native paint only: coordinates, identities, finite cells, endpoint topology, and sampled values remain semantic. An unknown style root address or view produces a compilation diagnostic rather than being silently ignored by native output.
The selected calculus-motion #:parameter-easing policy determines only intermediate vary, approach, and trace positions. Both 'linear and 'smoothstep preserve the same authored start, endpoint, and domain path.
63.2 Policies and headless inspection
The ordinary public values below construct immutable policy data or inspect immutable semantic data. They do not create native drawing objects.
procedure
(calculus-lesson? value) → boolean?
value : any/c (calculus-model? value) → boolean? value : any/c (calculus-component? value) → boolean? value : any/c (calculus-plan? value) → boolean? value : any/c (calculus-snapshot? value) → boolean? value : any/c (calculus-result? value) → boolean? value : any/c (calculus-moment? value) → boolean? value : any/c (calculus-profile? value) → boolean? value : any/c (calculus-theme? value) → boolean? value : any/c (calculus-style? value) → boolean? value : any/c (calculus-layout? value) → boolean? value : any/c (calculus-motion? value) → boolean? value : any/c (calculus-timing? value) → boolean? value : any/c (calculus-computation? value) → boolean? value : any/c (calculus-length? value) → boolean? value : any/c
procedure
(calculus-px value) → calculus-length?
value : real? (calculus-rel value) → calculus-length? value : real? (calculus-em value) → calculus-length? value : real?
procedure
(calculus-lesson-model lesson) → calculus-model?
lesson : calculus-lesson?
(calculus-model-at model [ #:values values #:computation computation]) → calculus-snapshot? model : calculus-model? values : hash? = (hash)
computation : calculus-computation? = default-calculus-computation
procedure
(calculus-plan-duration plan) → nonnegative-real?
plan : calculus-plan? (calculus-plan-diagnostics plan) → list? plan : calculus-plan? (calculus-snapshot-diagnostics snapshot) → list? snapshot : calculus-snapshot?
procedure
(calculus-step-start address) → calculus-moment?
address : (or/c symbol? list?) (calculus-step-end address) → calculus-moment? address : (or/c symbol? list?) (calculus-checkpoint address) → calculus-moment? address : (or/c symbol? list?)
procedure
(calculus-result-status result) → symbol?
result : calculus-result? (calculus-result-method result) → symbol? result : calculus-result? (calculus-result-approximate? result) → boolean? result : calculus-result? (calculus-result-value result) → any/c result : calculus-result? (calculus-result-message result) → (or/c #f string?) result : calculus-result? (calculus-result->datum result) → hash? result : calculus-result?
procedure
(calculus-style [ #:kind kind #:role role #:state state #:target target #:view view #:stroke stroke #:fill fill #:stroke-width stroke-width #:dash dash #:opacity opacity #:marker-radius marker-radius #:font-size font-size #:label-gap label-gap]) → calculus-style? kind : any/c = #f role : any/c = #f state : any/c = #f target : any/c = #f view : any/c = #f stroke : any/c = 'inherit fill : any/c = 'inherit stroke-width : any/c = 'inherit dash : any/c = 'inherit opacity : any/c = 'inherit marker-radius : any/c = 'inherit font-size : any/c = 'inherit label-gap : any/c = 'inherit
procedure
(calculus-theme [ #:base base #:background background #:foreground foreground #:font-family font-family #:font-size font-size #:rules rules]) → calculus-theme? base : any/c = #f background : any/c = #f foreground : any/c = #f font-family : any/c = #f font-size : any/c = #f rules : list? = '()
procedure
(calculus-layout [ #:arrangement arrangement #:panel-order panel-order #:margin margin #:gap gap #:captions? captions? #:caption-height caption-height #:label-policy label-policy #:fit-samples fit-samples]) → calculus-layout? arrangement : symbol? = 'auto panel-order : any/c = #f margin : calculus-length? = (calculus-rel 1/20) gap : calculus-length? = (calculus-rel 1/30) captions? : boolean? = #t caption-height : calculus-length? = (calculus-rel 7/50) label-policy : symbol? = 'stable fit-samples : exact-positive-integer? = 257
procedure
(calculus-motion [ #:graph-reveal graph-reveal #:line-reveal line-reveal #:reading reading #:parameter-easing parameter-easing #:refinement refinement #:limit-transition limit-transition #:focus focus #:highlight highlight #:reduced-motion? reduced-motion?]) → calculus-motion? graph-reveal : symbol? = 'trace line-reveal : symbol? = 'extend reading : symbol? = 'guided parameter-easing : symbol? = 'linear refinement : symbol? = 'subdivide limit-transition : symbol? = 'crossfade focus : symbol? = 'pan-zoom highlight : symbol? = 'outline reduced-motion? : boolean? = #f
procedure
(calculus-timing [ #:opening-pause opening-pause #:read-delay read-delay #:action-duration action-duration #:step-pause step-pause]) → calculus-timing? opening-pause : real? = 3/5 read-delay : real? = 1 action-duration : real? = 1 step-pause : real? = 3/5
procedure
(calculus-profile [ #:theme theme #:layout layout #:motion motion #:timing timing]) → calculus-profile? theme : calculus-theme? = light-calculus-theme layout : calculus-layout? = (calculus-layout) motion : calculus-motion? = (calculus-motion) timing : calculus-timing? = (calculus-timing)
procedure
(calculus-computation [ #:absolute-tolerance absolute-tolerance #:relative-tolerance relative-tolerance #:derivative-step derivative-step #:integration-method integration-method #:integration-budget integration-budget]) → calculus-computation? absolute-tolerance : real? = 1e-10 relative-tolerance : real? = 1e-8 derivative-step : real? = 0.0001 integration-method : symbol? = 'adaptive-simpson integration-budget : exact-positive-integer? = 10000
procedure
(compile-calculus-lesson lesson [ #:profile profile #:values values #:computation computation]) → calculus-plan? lesson : calculus-lesson? profile : calculus-profile? = default-calculus-profile values : hash? = (hash)
computation : calculus-computation? = default-calculus-computation
procedure
(calculus-plan-sample plan [#:at at]) → calculus-snapshot?
plan : calculus-plan? at : (or/c 'initial 'final real? calculus-moment?) = 'final
procedure
(calculus-snapshot-ref snapshot address) → calculus-result?
snapshot : calculus-snapshot? address : (or/c symbol? (listof symbol?))
procedure
(calculus-snapshot-visible? snapshot address [ #:view view]) → boolean? snapshot : calculus-snapshot? address : (or/c symbol? (listof symbol?)) view : (or/c #f symbol?) = #f
| (require animate/calculus/render) | package: animate |
The render adapter re-exports animate/calculus and is the explicit bridge to native output.
procedure
(calculus-render-quality [ #:curve-tolerance curve-tolerance #:max-depth max-depth]) → calculus-render-quality? curve-tolerance : real? = 1/2 max-depth : exact-positive-integer? = 18 (calculus-render-quality? value) → boolean? value : any/c
procedure
(prepare-calculus-lesson lesson [ #:profile profile #:values values #:computation computation #:width width #:height height #:formula-backend formula-backend #:quality quality]) → prepared-calculus-lesson? lesson : calculus-lesson? profile : calculus-profile? = default-calculus-profile values : hash? = (hash)
computation : calculus-computation? = default-calculus-computation width : exact-positive-integer? = 1280 height : exact-positive-integer? = 720 formula-backend : any/c = 'default quality : calculus-render-quality? = (calculus-render-quality)
procedure
(prepared-lesson->pict prepared [#:at at]) → pict?
prepared : prepared-calculus-lesson? at : any/c = 'final
procedure
(prepare-calculus-plan plan [ #:width width #:height height #:formula-backend formula-backend #:quality quality]) → prepared-calculus-lesson? plan : calculus-plan? width : exact-positive-integer? = 1280 height : exact-positive-integer? = 720 formula-backend : any/c = 'default quality : calculus-render-quality? = (calculus-render-quality) (prepared-calculus-lesson? value) → boolean? value : any/c (prepared-lesson-plan prepared) → calculus-plan? prepared : prepared-calculus-lesson? (prepared-lesson->scene prepared) → any/c prepared : prepared-calculus-lesson? (prepared-lesson->visual prepared [#:at at]) → any/c prepared : prepared-calculus-lesson? at : any/c = 'final
procedure
(lesson->pict lesson [ #:at at #:profile profile #:values values #:computation computation #:width width #:height height #:formula-backend formula-backend #:quality quality]) → pict? lesson : calculus-lesson? at : (or/c 'initial 'final real? calculus-moment?) = 'final profile : calculus-profile? = default-calculus-profile values : hash? = (hash)
computation : calculus-computation? = default-calculus-computation width : exact-positive-integer? = 1280 height : exact-positive-integer? = 720 formula-backend : any/c = 'default quality : calculus-render-quality? = (calculus-render-quality)
value
value
63.3 Release review
The repository-owned development runner calculus/review-examples.rkt is not part of either public calculus module. It prepares every complete Guide lesson once per selected profile and writes sparse, full-resolution PNG stills, contact sheets, optional short MP4 transition clips, a local HTML index, and a non-public evidence manifest. It refuses to replace an existing output directory. Use it after the automated native and process gates, for example:
|{ |
/Applications/Racket\ v9.3.0.2/bin/racket calculus/review-examples.rkt \ |
--all --profiles light,dark,textbook --workers 10 --clips --output calculus-review |
}| |
The –workers value is recorded with the review evidence. Sparse stills are made from the shared prepared Pict adapter and do not send Pict closures to workers; calculus/run-tests.rkt –process separately verifies the real reconstructible project-rendering worker path. –clips requires ffmpeg on PATH; omit it when only still evidence is needed.