% !TEX program = xelatex \documentclass[10pt,letterpaper,twocolumn]{article} % === GEOMETRY === \usepackage[top=0.75in, bottom=0.75in, left=0.75in, right=0.75in]{geometry} % === FONTS === \usepackage{fontspec} \usepackage{unicode-math} \setmainfont{Latin Modern Roman} \setsansfont{Latin Modern Sans} \setmonofont{Latin Modern Mono}[Scale=0.85] \newfontfamily\acbold{ywft-processing-bold}[ Path=../../system/public/type/webfonts/, Extension=.ttf ] \newfontfamily\aclight{ywft-processing-light}[ Path=../../system/public/type/webfonts/, Extension=.ttf ] % === PACKAGES === \usepackage{xcolor} \usepackage{titlesec} \usepackage{enumitem} \usepackage{booktabs} \usepackage{tabularx} \usepackage{fancyhdr} \usepackage{hyperref} \usepackage{graphicx} \usepackage{ragged2e} \usepackage{microtype} \usepackage{listings} \usepackage{natbib} \usepackage[colorspec=0.92]{draftwatermark} % === COLORS === \definecolor{acpink}{RGB}{180,72,135} \definecolor{acpurple}{RGB}{120,80,180} \definecolor{acdark}{RGB}{64,56,74} \definecolor{acgray}{RGB}{119,119,119} \definecolor{draftcolor}{RGB}{180,72,135} % === DRAFT WATERMARK === \DraftwatermarkOptions{ text=WORKING DRAFT, fontsize=3cm, color=draftcolor!18, angle=45, pos={0.5\paperwidth, 0.5\paperheight} } % === JS SYNTAX COLORS === \definecolor{jskw}{RGB}{119,51,170} \definecolor{jsfn}{RGB}{0,136,170} \definecolor{jsstr}{RGB}{170,120,0} \definecolor{jsnum}{RGB}{204,0,102} \definecolor{jscmt}{RGB}{102,102,102} % === PROCESSING SYNTAX COLORS === \definecolor{pjkw}{RGB}{204,102,0} \definecolor{pjfn}{RGB}{0,102,153} \definecolor{pjcmt}{RGB}{102,102,102} % === HYPERREF === \hypersetup{ colorlinks=true, linkcolor=acpurple, urlcolor=acpurple, citecolor=acpurple, pdfauthor={@jeffrey}, pdftitle={From setup() to boot(): Processing at the Core of the Piece API}, } % === SECTION FORMATTING === \titleformat{\section} {\normalfont\bfseries\normalsize\uppercase} {\thesection.} {0.5em} {} \titlespacing{\section}{0pt}{1.2em}{0.3em} \titleformat{\subsection} {\normalfont\bfseries\small} {\thesubsection} {0.5em} {} \titlespacing{\subsection}{0pt}{0.8em}{0.2em} \titleformat{\subsubsection} {\normalfont\itshape\small} {\thesubsubsection} {0.5em} {} \titlespacing{\subsubsection}{0pt}{0.6em}{0.1em} % === HEADER/FOOTER === \pagestyle{fancy} \fancyhf{} \renewcommand{\headrulewidth}{0pt} \fancyhead[C]{\footnotesize\color{draftcolor}\textit{Working Draft --- not for citation}} \fancyfoot[C]{\footnotesize\thepage} % === LIST SETTINGS === \setlist[itemize]{nosep, leftmargin=1.2em, itemsep=0.1em} \setlist[enumerate]{nosep, leftmargin=1.2em} % === COLUMN SEPARATION === \setlength{\columnsep}{1.8em} % === PARAGRAPH SETTINGS === \setlength{\parindent}{1em} \setlength{\parskip}{0.3em} % Hyphenation for narrow two-column layout \tolerance=800 \emergencystretch=1em \hyphenpenalty=50 % === LISTINGS === \lstdefinelanguage{processing}{ morekeywords=[1]{void,int,float,boolean,color,String,class,new,if,else,for,while,return,public,private,extends,import}, morekeywords=[2]{setup,draw,mousePressed,mouseDragged,keyPressed,size,background,stroke,noStroke,fill,noFill,line,rect,ellipse,point,triangle,beginShape,endShape,vertex,translate,rotate,scale,pushMatrix,popMatrix,frameRate,width,height,mouseX,mouseY,pmouseX,pmouseY,key,keyCode,mouseButton,frameCount}, sensitive=true, morecomment=[l]{//}, morecomment=[s]{/*}{*/}, morestring=[b]", } \lstdefinelanguage{p5js}{ morekeywords=[1]{function,let,const,var,if,else,for,while,return,new,class,export}, morekeywords=[2]{setup,draw,mousePressed,mouseDragged,keyPressed,createCanvas,background,stroke,noStroke,fill,noFill,line,rect,ellipse,point,triangle,beginShape,endShape,vertex,translate,rotate,scale,push,pop,frameRate,width,height,mouseX,mouseY,pmouseX,pmouseY,key,keyCode,mouseButton,frameCount,createGraphics,random,noise,map,constrain,dist,lerp}, sensitive=true, morecomment=[l]{//}, morestring=[b]", morestring=[b]', morestring=[b]`, } \lstdefinelanguage{acjs}{ morekeywords=[1]{function,export,const,let,var,return,if,else,new,async,await,import,from,for}, morekeywords=[2]{wipe,ink,line,box,circle,write,screen,params,colon,jump,send,store,net,sound,speaker,pen,event,boot,paint,act,sim,leave,paste,plot,poly,flood,form,cursor,handle,num,geo,ui}, sensitive=true, morecomment=[l]{//}, morestring=[b]", morestring=[b]', morestring=[b]`, } \lstdefinestyle{processingstyle}{ language=processing, keywordstyle=[1]\color{pjkw}\bfseries, keywordstyle=[2]\color{pjfn}\bfseries, commentstyle=\color{pjcmt}\itshape, stringstyle=\color{jsstr}, } \lstdefinestyle{p5style}{ language=p5js, keywordstyle=[1]\color{jskw}\bfseries, keywordstyle=[2]\color{pjfn}\bfseries, commentstyle=\color{jscmt}\itshape, stringstyle=\color{jsstr}, } \lstdefinestyle{acjsstyle}{ language=acjs, keywordstyle=[1]\color{jskw}\bfseries, keywordstyle=[2]\color{jsfn}\bfseries, commentstyle=\color{jscmt}\itshape, stringstyle=\color{jsstr}, } \lstset{ basicstyle=\ttfamily\small, breaklines=true, frame=single, rulecolor=\color{acgray!30}, backgroundcolor=\color{acgray!5}, xleftmargin=0.5em, xrightmargin=0.5em, aboveskip=0.5em, belowskip=0.5em, numbers=none, tabsize=2, } \newcommand{\acdot}{{\color{acpink}.}} \newcommand{\ac}{\textsc{Aesthetic.Computer}} % Random caps for Aesthetic.Computer branding \newcount\acrandtmp \newcommand{\acrandletter}[2]{% \acrandtmp=\uniformdeviate 2\relax \ifnum\acrandtmp=0\relax#1\else#2\fi% } \newcommand{\acrandname}{% \acrandletter{a}{A}\acrandletter{e}{E}\acrandletter{s}{S}\acrandletter{t}{T}% \acrandletter{h}{H}\acrandletter{e}{E}\acrandletter{t}{T}\acrandletter{i}{I}% \acrandletter{c}{C}{\color{acpink}.}\acrandletter{c}{C}\acrandletter{o}{O}% \acrandletter{m}{M}\acrandletter{p}{P}\acrandletter{u}{U}\acrandletter{t}{T}% \acrandletter{e}{E}\acrandletter{r}{R}% } \begin{document} % ============ TITLE BLOCK ============ \twocolumn[{% \begin{center} {\acbold\fontsize{22pt}{26pt}\selectfont\color{acdark} From \texttt{setup()} to \texttt{boot()}}\par \vspace{0.2em} {\aclight\fontsize{11pt}{13pt}\selectfont\color{acpink} Processing at the Core of the Piece API}\par \vspace{0.6em} {\normalsize\href{https://prompt.ac/@jeffrey}{@jeffrey}}\par {\small\color{acgray} Aesthetic.Computer}\par {\small\color{acgray} ORCID: \href{https://orcid.org/0009-0007-4460-4913}{0009-0007-4460-4913}}\par \vspace{0.3em} {\small\color{acpurple} \url{https://aesthetic.computer}}\par \vspace{0.6em} \rule{\textwidth}{1.5pt} \vspace{0.5em} \end{center} \begin{center} {\small\color{draftcolor}\textbf{[ working draft --- not for citation ]}} \end{center} \vspace{0.3em} \begin{quote} \small\noindent\textbf{Abstract.} Every creative coding platform defines a core API---a small set of functions through which programs see the world and draw on it. Processing's \texttt{setup()}/\texttt{draw()} with global drawing primitives (\texttt{background()}, \texttt{stroke()}, \texttt{ellipse()}) established a pattern in 2001 that has shaped two decades of creative coding tools. p5.js brought this model to the browser in 2014, preserving the API surface while adapting to JavaScript and the DOM. \ac{} (AC), begun in 2021, carries Processing's thinking at its core while extending the model in several structural ways: it expands the two-function lifecycle to five (\texttt{boot}, \texttt{paint}, \texttt{act}, \texttt{sim}, \texttt{leave}), eliminates global state in favor of destructured API injection, separates simulation from rendering at different tick rates, and makes every program URL-addressable with no build step. This paper traces how Processing's ideas live inside the AC piece API, comparing the lifecycle models, drawing primitives, input handling, and state management strategies across Design By Numbers, Processing, p5.js, and AC. We argue that the AC API design---with Processing's immediate-mode graphics model at its foundation---extends the \emph{sketchbook} metaphor (write, run, discard) into an \emph{instrument} metaphor (boot, play, practice, return). \end{quote} \vspace{0.5em} }] % ============ 1. INTRODUCTION ============ \section{Introduction} The history of creative coding APIs is a history of deciding what the programmer should say first. In Design By Numbers~\citep{maeda2001dbn}, the first statement was a coordinate and a grayscale value: \texttt{Paper 50}. In Processing~\citep{reas2003processing}, it was \texttt{size(200, 200)} inside \texttt{setup()}. In p5.js~\citep{mccarthy2015p5js}, it was \texttt{createCanvas(400, 400)}. In \ac{}, the programmer says nothing about the canvas at all---the runtime provides \texttt{screen.width} and \texttt{screen.height} as given facts, and the first meaningful statement is typically \texttt{wipe()}, clearing the screen to begin painting. These are not arbitrary differences. Each reflects a decision about what the platform assumes versus what the programmer must specify, and these decisions accumulate into fundamentally different relationships between author and machine. This paper traces the API lineage from Processing through p5.js to AC, examining each transition as a set of design moves: what was kept, what was changed, and what the change implies. The contribution is threefold: (1) a detailed technical comparison of the lifecycle models, drawing APIs, input systems, and state management strategies of Processing, p5.js, and AC; (2) an analysis of the design rationale behind AC's departures from the Processing model; and (3) an argument that the AC piece API embodies a shift from the sketchbook metaphor to what we call the \emph{instrument metaphor}---a model where the relationship between programmer and program is ongoing, performative, and practice-based rather than exploratory and disposable. % ============ 2. THE PROCESSING MODEL ============ \section{The Processing Model (2001)} \label{sec:processing} Processing~\citep{reas2007processing} was designed as a ``software sketchbook'' for visual artists. Its API centers on two lifecycle functions and a library of global drawing primitives. \subsection{Lifecycle: \texttt{setup()} and \texttt{draw()}} \begin{lstlisting}[style=processingstyle,caption={Minimal Processing sketch.}] void setup() { size(400, 400); background(0); } void draw() { stroke(255); ellipse(mouseX, mouseY, 20, 20); } \end{lstlisting} \texttt{setup()} runs once; \texttt{draw()} runs every frame at a default 60fps. This two-function model is Processing's most influential design decision. It reduces the cognitive overhead of animation from managing a render loop to filling in two blanks: ``what happens once?'' and ``what happens every frame?'' The model is deliberately minimal. There is no explicit \texttt{input()} function---mouse and keyboard state are available as global variables (\texttt{mouseX}, \texttt{mouseY}, \texttt{key}, \texttt{keyCode}) that update automatically. Event callbacks (\texttt{mousePressed()}, \texttt{keyPressed()}) exist but are optional supplements, not required entry points. \subsection{Drawing primitives} Processing's drawing API uses a \emph{stateful pipeline} model inherited from PostScript and OpenGL: state-setting calls (\texttt{stroke()}, \texttt{fill()}, \texttt{strokeWeight()}) modify a persistent graphics context, and shape calls (\texttt{ellipse()}, \texttt{rect()}, \texttt{line()}) render using that context. The context persists across frames unless explicitly reset. \begin{lstlisting}[style=processingstyle,caption={Stateful drawing context.}] void draw() { fill(255, 0, 0); // Set fill: red stroke(0); // Set stroke: black strokeWeight(3); // Set weight: 3px ellipse(100, 100, 50, 50); // Uses above rect(200, 100, 50, 50); // Also uses above // State persists into next frame } \end{lstlisting} This state persistence is both powerful (less code for uniform styles) and error-prone (forgotten state leaks across frames). Processing addresses this with \texttt{pushStyle()}/\texttt{popStyle()} and \texttt{pushMatrix()}/\texttt{popMatrix()}, but these are expert-level tools. \subsection{Global scope} All Processing programs share a single global namespace. Variables declared outside \texttt{setup()} and \texttt{draw()} are accessible everywhere. The drawing functions (\texttt{line()}, \texttt{ellipse()}, \texttt{background()}) are global. Input variables (\texttt{mouseX}, \texttt{mouseY}) are global. This eliminates the need to understand scope, imports, or dependency injection---critical for beginners---but makes programs impossible to compose or isolate. % ============ 3. THE P5.JS TRANSITION ============ \section{The p5.js Transition (2014)} \label{sec:p5js} p5.js~\citep{mccarthy2015p5js} is a JavaScript reimplementation of Processing. Its primary contribution is bringing the Processing model to the browser, but the port required several adaptations. \subsection{Lifecycle preservation} \begin{lstlisting}[style=p5style,caption={Minimal p5.js sketch.}] function setup() { createCanvas(400, 400); } function draw() { background(220); ellipse(mouseX, mouseY, 50, 50); } \end{lstlisting} The \texttt{setup()}/\texttt{draw()} model is preserved exactly. The cognitive model is identical: two functions, global drawing primitives, automatic animation loop. This continuity is deliberate---p5.js aims to be Processing for the web, not a new language. \subsection{Canvas creation} The most visible change is \texttt{createCanvas()} replacing \texttt{size()}. This is not cosmetic: in Processing, \texttt{size()} configures the application window; in p5.js, \texttt{createCanvas()} creates an HTML \texttt{} element within the DOM. The sketch must negotiate with the existing page rather than owning the entire display. \subsection{Instance mode} p5.js introduces an important escape hatch from the global namespace: \emph{instance mode}. \begin{lstlisting}[style=p5style,caption={p5.js instance mode.}] const sketch = (p) => { p.setup = () => { p.createCanvas(400, 400); }; p.draw = () => { p.background(220); p.ellipse(p.mouseX, p.mouseY, 50, 50); }; }; new p5(sketch); \end{lstlisting} Instance mode wraps all API functions behind a namespace (\texttt{p.}), allowing multiple sketches on one page and avoiding global pollution. However, most p5.js code is written in global mode, and instance mode is typically encountered only when embedding sketches in larger applications. The prefix notation (\texttt{p.ellipse} vs.\ \texttt{ellipse}) increases verbosity and reduces the ``just write'' quality that makes Processing inviting. \subsection{What changed, what didn't} p5.js preserved: the two-function lifecycle, global drawing primitives, stateful graphics context, frame-based animation, and the ``sketch'' identity. It adapted: canvas creation to the DOM, renderer selection (2D/WebGL), event handling to browser events, and added instance mode for composition. It did not address: the conflation of simulation and rendering, the lack of structured input handling, or the single-file isolation problem. % ============ 4. THE AC PIECE API ============ \section{The AC Piece API (2021--)} \label{sec:ac} \ac{}'s piece API~\citep{scudder2026ac} is built on Processing's core ideas---immediate-mode graphics, single-file programs, lifecycle functions---and extends them around five concerns instead of two. \subsection{Five lifecycle functions} \begin{lstlisting}[style=acjsstyle,caption={Minimal AC piece.}] function boot({ screen, params }) { // Runs once on load } function paint({ wipe, ink, line, screen }) { wipe("navy"); ink("pink").circle( screen.width / 2, screen.height / 2, 50 ); } function act({ event: e }) { if (e.is("keyboard:down:space")) { // Handle spacebar } } function sim() { // Update state at 120fps } export { boot, paint, act, sim }; \end{lstlisting} The five functions are: \begin{itemize} \item \texttt{boot(\$api)} --- runs once when the piece loads. Extends Processing's \texttt{setup()}, with the screen provided by the runtime rather than configured by the programmer. \item \texttt{paint(\$api)} --- runs every frame that needs rendering. Carries forward \texttt{draw()}'s immediate-mode model, but is purely visual: no logic, no state mutation (by convention). \item \texttt{act(\$api)} --- called once per input event. Consolidates Processing's event callbacks (\texttt{mousePressed()}, \texttt{keyPressed()}) into a single, unified entry point. \item \texttt{sim(\$api)} --- runs at a fixed 120Hz, potentially multiple times per rendered frame. Has no equivalent in Processing; closest analogue is the fixed-timestep game loop~\citep{nystrom2014game}. \item \texttt{leave(\$api)} --- cleanup on exit. No equivalent in Processing, where sketches simply terminate. \end{itemize} Each function is optional. A piece that exports only \texttt{paint} is a valid, functioning program. \subsection{API injection via destructuring} The most structurally significant extension of the Processing model is that \textbf{no API functions exist in the global scope}. Every function the piece uses is received as a parameter: \begin{lstlisting}[style=acjsstyle,caption={API destructuring in AC.}] function paint({ wipe, ink, line, box, circle, screen, num }) { wipe(0, 0, 30); ink(255, 100, 180); const cx = num.lerp(0, screen.width, 0.5); circle(cx, screen.height / 2, 40); } \end{lstlisting} This design has several consequences: \begin{enumerate} \item \textbf{No global pollution.} Module-level variables are piece state; API functions are parameters. There is no ambient namespace to collide with. \item \textbf{Self-documenting imports.} The destructuring pattern at the top of each function declares exactly which API surfaces the function uses, serving as an inline dependency manifest. \item \textbf{Composability.} Multiple pieces can coexist in the same JavaScript context without API collisions, enabling the platform's piece-switching and embedding mechanisms. \item \textbf{Discoverability.} Autocompletion in editors works on the destructured parameter object, providing a natural way to explore the API. \end{enumerate} This is the p5.js instance mode pattern taken to its conclusion: instead of prefixing every call with \texttt{p.}, the programmer destructures exactly the functions they need, once, at the function signature. \subsection{Separation of simulation and rendering} \label{sec:simsep} Processing's \texttt{draw()} conflates two concerns: updating state and rendering pixels. This works for simple sketches but creates problems as complexity grows: physics simulations tied to frame rate, input latency coupled to rendering cost, and difficulty separating ``what happened'' from ``what it looks like.'' AC separates these explicitly: \begin{itemize} \item \texttt{sim()} runs at a fixed 120Hz, independent of display refresh rate. On a 60Hz display, \texttt{sim()} runs twice per \texttt{paint()} call. On a 144Hz display, the ratio adjusts accordingly. \item \texttt{paint()} runs at the display's refresh rate (capped at approximately 165fps), and is responsible only for rendering the current state. \item \texttt{act()} runs once per input event, immediately when the event arrives. \end{itemize} This three-way split mirrors the architecture of modern game engines~\citep{nystrom2014game}: a fixed update tick for deterministic logic, a variable render tick for smooth display, and an event queue for input. The difference is that AC exposes this architecture as a first-class API rather than hiding it behind a framework. \subsection{Unified event handling} Processing distributes input handling across global variables and optional callbacks: \begin{lstlisting}[style=processingstyle] // Processing: scattered input model void draw() { if (mousePressed) { /* poll state */ } } void mousePressed() { /* callback */ } void keyPressed() { /* callback */ } void mouseDragged() { /* callback */ } \end{lstlisting} AC consolidates all input into \texttt{act()} with a string-based event matching system: \begin{lstlisting}[style=acjsstyle] function act({ event: e, pen }) { if (e.is("touch")) { } if (e.is("draw")) { } if (e.is("lift")) { } if (e.is("keyboard:down:a")) { } if (e.is("keyboard:down:space")){ } if (e.is("gamepad:a")) { } if (e.is("reframed")) { } } \end{lstlisting} The \texttt{event.is()} pattern provides a uniform interface across input modalities (touch, mouse, keyboard, gamepad, MIDI, hand tracking) through a single function. Event strings are hierarchical (\texttt{keyboard:down:a}) and can match at any level of specificity. This replaces the combinatorial explosion of Processing callbacks with a single, filterable stream. \subsection{Drawing primitives: stateless by default} Processing and p5.js use a stateful graphics context where \texttt{fill()}, \texttt{stroke()}, and transformation calls persist until explicitly changed. AC inverts this: the \texttt{ink()} function sets color for the \emph{immediately following} draw call and returns the API object for chaining: \begin{lstlisting}[style=acjsstyle] function paint({ wipe, ink, line, circle }) { wipe("black"); ink("red").circle(50, 50, 20); ink("blue").line(0, 0, 100, 100); // No state leaks between calls } \end{lstlisting} The \texttt{ink()} return-and-chain pattern makes color-shape pairs visually atomic: each drawing operation is a self-contained expression rather than a sequence of context mutations. This eliminates the class of bugs where forgotten \texttt{fill()} or \texttt{stroke()} calls from a previous frame (or a previous function) bleed into unrelated drawing. The \texttt{wipe()} function replaces Processing's \texttt{background()}, using a shorter, more active verb. This naming is deliberate: ``wipe'' suggests a physical action (erasing a surface) rather than a property setting. \subsection{No canvas configuration} In Processing, the first line of \texttt{setup()} is typically \texttt{size(w, h)}. In p5.js, it is \texttt{createCanvas(w, h)}. In AC, there is no equivalent call. The runtime provides the canvas at the device's native resolution, and pieces receive \texttt{screen.width} and \texttt{screen.height} as read-only properties. This reflects a mobile-first design philosophy: on phones and tablets, the ``correct'' canvas size is the device screen. Allowing the programmer to specify dimensions creates a mismatch between the fixed canvas and the variable viewport. AC eliminates this mismatch by making the canvas responsive by default. % ============ 5. API SURFACE COMPARISON ============ \section{API Surface Comparison} \label{sec:comparison} Table~\ref{tab:lifecycle} compares the lifecycle models. Table~\ref{tab:drawing} compares drawing primitives. \begin{table}[h] \small \centering \begin{tabularx}{\columnwidth}{lXXX} \toprule & \textbf{Processing} & \textbf{p5.js} & \textbf{AC} \\ \midrule Init & \texttt{setup()} & \texttt{setup()} & \texttt{boot(\$)} \\ Render & \texttt{draw()} & \texttt{draw()} & \texttt{paint(\$)} \\ Logic & (in draw) & (in draw) & \texttt{sim(\$)} \\ Input & callbacks & callbacks & \texttt{act(\$)} \\ Cleanup & --- & \texttt{remove()} & \texttt{leave(\$)} \\ \midrule Render rate & 60fps & 60fps & display Hz \\ Logic rate & 60fps & 60fps & 120fps fixed \\ Scope & global & global/inst. & injected \\ \bottomrule \end{tabularx} \caption{Lifecycle comparison. \texttt{\$} denotes destructured API injection.} \label{tab:lifecycle} \end{table} \begin{table}[h] \small \centering \begin{tabularx}{\columnwidth}{lXX} \toprule \textbf{Processing/p5} & \textbf{AC} & \textbf{Notes} \\ \midrule \texttt{background()} & \texttt{wipe()} & Verb, not property \\ \texttt{fill() + stroke()} & \texttt{ink()} & Unified, chainable \\ \texttt{ellipse()} & \texttt{circle()} & Named for shape \\ \texttt{rect()} & \texttt{box()} & Shorter name \\ \texttt{line()} & \texttt{line()} & Unchanged \\ \texttt{point()} & \texttt{plot()} & Graph metaphor \\ \texttt{text()} & \texttt{write()} & Active verb \\ --- & \texttt{flood()} & Fill region \\ --- & \texttt{paste()} & Buffer compositing \\ --- & \texttt{form()} & 3D rendering \\ \bottomrule \end{tabularx} \caption{Drawing primitive comparison.} \label{tab:drawing} \end{table} \subsection{Naming philosophy} Processing's API names are descriptive nouns and adjectives: \texttt{background}, \texttt{ellipse}, \texttt{rect}, \texttt{stroke}, \texttt{fill}. They describe \emph{what} is being set or drawn. AC's names are active verbs: \texttt{wipe}, \texttt{ink}, \texttt{plot}, \texttt{write}, \texttt{flood}, \texttt{paste}. They describe \emph{what the programmer is doing}---physical actions performed on a surface. This shift from descriptive to imperative naming aligns with the instrument metaphor: an instrument's interface is understood through verbs (press, blow, strike, pluck), not nouns. The AC API reads as a sequence of actions: ``wipe the screen, ink it pink, draw a circle, write some text.'' \subsection{Color model} Processing uses separate \texttt{fill()} and \texttt{stroke()} calls, each accepting RGB, HSB, or hex values. The fill/stroke distinction maps to vector graphics (SVG, PostScript) where shapes have interior color and boundary color. AC uses a single \texttt{ink()} call that sets color for all subsequent operations. There is no fill/stroke distinction: a \texttt{circle()} is filled or stroked based on its parameters, not on ambient context. The \texttt{ink()} function accepts: \begin{itemize} \item RGB values: \texttt{ink(255, 100, 50)} \item Named colors: \texttt{ink("pink")}, \texttt{ink("navy")} \item Grayscale: \texttt{ink(128)} \item Alpha: \texttt{ink(255, 0, 0, 128)} \end{itemize} Named colors are a significant usability choice for beginners. Where Processing requires \texttt{fill(255, 192, 203)} for pink, AC accepts \texttt{ink("pink")}. The named color vocabulary is intentionally small and evocative, closer to a paint box than a color picker. % ============ 6. STATE MANAGEMENT ============ \section{State Management} \label{sec:state} \subsection{Processing: global variables} \begin{lstlisting}[style=processingstyle] int x = 100; int y = 100; void draw() { background(0); x += 1; ellipse(x, y, 20, 20); } \end{lstlisting} State in Processing lives in global variables. This is simple but has well-known problems: all state is mutable from anywhere, there is no encapsulation, and program state is indistinguishable from API state. \subsection{AC: module-level closures} \begin{lstlisting}[style=acjsstyle] let x = 100; let y = 100; function sim() { x += 1; } function paint({ wipe, ink, circle }) { wipe(0); ink(255).circle(x, y, 20); } export { sim, paint }; \end{lstlisting} AC pieces are ES modules. Variables declared at module scope are private to the piece---invisible to the runtime, other pieces, and the global scope. The \texttt{export} statement makes only the lifecycle functions visible. This is not a convention enforced by documentation; it is a guarantee of the JavaScript module system. The separation of state mutation (\texttt{sim}) from state rendering (\texttt{paint}) encourages a discipline where \texttt{paint} is a pure function of module state---it reads variables and draws, but does not modify them. This is not enforced, but the API structure makes it the natural pattern. % ============ 7. THE GENEALOGY ============ \section{The Genealogy} \label{sec:genealogy} \subsection{Design By Numbers (1999)} Maeda's Design By Numbers~\citep{maeda2001dbn} introduced the core insight: a programming environment for visual output, with the simplest possible API. DBN had no animation loop---programs ran once, top to bottom. The primitive set was minimal: \texttt{Paper} (background), \texttt{Pen} (stroke weight), \texttt{Line}, \texttt{Set} (pixel), and control flow. The entire language could be learned in an afternoon. AC inherits DBN's minimalism in naming (short, active verbs) and its conviction that the API should be exhaustively learnable. \subsection{Processing (2001)} Processing~\citep{reas2003processing} added what DBN lacked: animation (\texttt{draw()} loop), interaction (\texttt{mouseX/Y}), and a richer primitive set. It also added what DBN deliberately avoided: state (the graphics context), a standard library (math, typography, image loading), and a compilation step (Java). Processing's greatest innovation was not any single function but the \texttt{setup()}/\texttt{draw()} pair: the simplest possible expression of interactive animation. AC inherits the lifecycle function model but splits \texttt{draw()} into three concerns (\texttt{paint}, \texttt{sim}, \texttt{act}). \subsection{p5.js (2014)} p5.js~\citep{mccarthy2015p5js} brought Processing to the browser, making sketches instantly shareable via URL. This was a prerequisite for AC: the browser as creative platform. p5.js also introduced instance mode, foreshadowing AC's API injection pattern. AC inherits the browser-native assumption and the shareability principle (every piece is a URL), but replaces the library-in-a-page model with a full runtime: pieces do not include a \texttt{