Monorepo for Aesthetic.Computer
aesthetic.computer
1% !TEX program = xelatex
2\documentclass[10pt,letterpaper,twocolumn]{article}
3
4% === GEOMETRY ===
5\usepackage[top=0.75in, bottom=0.75in, left=0.75in, right=0.75in]{geometry}
6
7% === FONTS ===
8\usepackage{fontspec}
9\usepackage{unicode-math}
10\setmainfont{Latin Modern Roman}
11\setsansfont{Latin Modern Sans}
12\setmonofont{Latin Modern Mono}[Scale=0.85]
13\newfontfamily\acbold{ywft-processing-bold}[
14 Path=../../system/public/type/webfonts/,
15 Extension=.ttf
16]
17\newfontfamily\aclight{ywft-processing-light}[
18 Path=../../system/public/type/webfonts/,
19 Extension=.ttf
20]
21
22% === PACKAGES ===
23\usepackage{xcolor}
24\usepackage{titlesec}
25\usepackage{enumitem}
26\usepackage{booktabs}
27\usepackage{tabularx}
28\usepackage{fancyhdr}
29\usepackage{hyperref}
30\usepackage{graphicx}
31\usepackage{ragged2e}
32\usepackage{microtype}
33\usepackage{listings}
34\usepackage{natbib}
35\usepackage[colorspec=0.92]{draftwatermark}
36
37% === COLORS ===
38\definecolor{acpink}{RGB}{180,72,135}
39\definecolor{acpurple}{RGB}{120,80,180}
40\definecolor{acdark}{RGB}{64,56,74}
41\definecolor{acgray}{RGB}{119,119,119}
42\definecolor{draftcolor}{RGB}{180,72,135}
43
44% === DRAFT WATERMARK ===
45\DraftwatermarkOptions{
46 text=WORKING DRAFT,
47 fontsize=3cm,
48 color=draftcolor!18,
49 angle=45,
50 pos={0.5\paperwidth, 0.5\paperheight}
51}
52
53% === JS SYNTAX COLORS ===
54\definecolor{jskw}{RGB}{119,51,170}
55\definecolor{jsfn}{RGB}{0,136,170}
56\definecolor{jsstr}{RGB}{170,120,0}
57\definecolor{jsnum}{RGB}{204,0,102}
58\definecolor{jscmt}{RGB}{102,102,102}
59
60% === PROCESSING SYNTAX COLORS ===
61\definecolor{pjkw}{RGB}{204,102,0}
62\definecolor{pjfn}{RGB}{0,102,153}
63\definecolor{pjcmt}{RGB}{102,102,102}
64
65% === HYPERREF ===
66\hypersetup{
67 colorlinks=true,
68 linkcolor=acpurple,
69 urlcolor=acpurple,
70 citecolor=acpurple,
71 pdfauthor={@jeffrey},
72 pdftitle={Fra setup() til boot(): Processing i kernen af Piece-API'en},
73}
74
75% === SECTION FORMATTING ===
76\titleformat{\section}
77 {\normalfont\bfseries\normalsize\uppercase}
78 {\thesection.}
79 {0.5em}
80 {}
81\titlespacing{\section}{0pt}{1.2em}{0.3em}
82
83\titleformat{\subsection}
84 {\normalfont\bfseries\small}
85 {\thesubsection}
86 {0.5em}
87 {}
88\titlespacing{\subsection}{0pt}{0.8em}{0.2em}
89
90\titleformat{\subsubsection}
91 {\normalfont\itshape\small}
92 {\thesubsubsection}
93 {0.5em}
94 {}
95\titlespacing{\subsubsection}{0pt}{0.6em}{0.1em}
96
97% === HEADER/FOOTER ===
98\pagestyle{fancy}
99\fancyhf{}
100\renewcommand{\headrulewidth}{0pt}
101\fancyhead[C]{\footnotesize\color{draftcolor}\textit{Arbejdsudkast --- ikke til citation}}
102\fancyfoot[C]{\footnotesize\thepage}
103
104% === LIST SETTINGS ===
105\setlist[itemize]{nosep, leftmargin=1.2em, itemsep=0.1em}
106\setlist[enumerate]{nosep, leftmargin=1.2em}
107
108% === COLUMN SEPARATION ===
109\setlength{\columnsep}{1.8em}
110
111% === PARAGRAPH SETTINGS ===
112\setlength{\parindent}{1em}
113\setlength{\parskip}{0.3em}
114
115% Hyphenation for narrow two-column layout
116\tolerance=800
117\emergencystretch=1em
118\hyphenpenalty=50
119
120% === LISTINGS ===
121\lstdefinelanguage{processing}{
122 morekeywords=[1]{void,int,float,boolean,color,String,class,new,if,else,for,while,return,public,private,extends,import},
123 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},
124 sensitive=true,
125 morecomment=[l]{//},
126 morecomment=[s]{/*}{*/},
127 morestring=[b]",
128}
129
130\lstdefinelanguage{p5js}{
131 morekeywords=[1]{function,let,const,var,if,else,for,while,return,new,class,export},
132 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},
133 sensitive=true,
134 morecomment=[l]{//},
135 morestring=[b]",
136 morestring=[b]',
137 morestring=[b]`,
138}
139
140\lstdefinelanguage{acjs}{
141 morekeywords=[1]{function,export,const,let,var,return,if,else,new,async,await,import,from,for},
142 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},
143 sensitive=true,
144 morecomment=[l]{//},
145 morestring=[b]",
146 morestring=[b]',
147 morestring=[b]`,
148}
149
150\lstdefinestyle{processingstyle}{
151 language=processing,
152 keywordstyle=[1]\color{pjkw}\bfseries,
153 keywordstyle=[2]\color{pjfn}\bfseries,
154 commentstyle=\color{pjcmt}\itshape,
155 stringstyle=\color{jsstr},
156}
157
158\lstdefinestyle{p5style}{
159 language=p5js,
160 keywordstyle=[1]\color{jskw}\bfseries,
161 keywordstyle=[2]\color{pjfn}\bfseries,
162 commentstyle=\color{jscmt}\itshape,
163 stringstyle=\color{jsstr},
164}
165
166\lstdefinestyle{acjsstyle}{
167 language=acjs,
168 keywordstyle=[1]\color{jskw}\bfseries,
169 keywordstyle=[2]\color{jsfn}\bfseries,
170 commentstyle=\color{jscmt}\itshape,
171 stringstyle=\color{jsstr},
172}
173
174\lstset{
175 basicstyle=\ttfamily\small,
176 breaklines=true,
177 frame=single,
178 rulecolor=\color{acgray!30},
179 backgroundcolor=\color{acgray!5},
180 xleftmargin=0.5em,
181 xrightmargin=0.5em,
182 aboveskip=0.5em,
183 belowskip=0.5em,
184 numbers=none,
185 tabsize=2,
186}
187
188\newcommand{\acdot}{{\color{acpink}.}}
189\newcommand{\ac}{\textsc{Aesthetic.Computer}}
190
191\begin{document}
192
193% ============ TITLE BLOCK ============
194
195\twocolumn[{%
196\begin{center}
197{\acbold\fontsize{22pt}{26pt}\selectfont\color{acdark} Fra \texttt{setup()} til \texttt{boot()}}\par
198\vspace{0.2em}
199{\aclight\fontsize{11pt}{13pt}\selectfont\color{acpink} Processing i kernen af Piece-API'en}\par
200\vspace{0.6em}
201{\normalsize\href{https://prompt.ac/@jeffrey}{@jeffrey}}\par
202{\small\color{acgray} Aesthetic.Computer}\par
203{\small\color{acgray} ORCID: \href{https://orcid.org/0009-0007-4460-4913}{0009-0007-4460-4913}}\par
204\vspace{0.3em}
205{\small\color{acpurple} \url{https://aesthetic.computer}}\par
206\vspace{0.6em}
207\rule{\textwidth}{1.5pt}
208\vspace{0.5em}
209\end{center}
210
211\begin{center}
212{\small\color{draftcolor}\textbf{[ arbejdsudkast --- ikke til citation ]}}
213\end{center}
214\vspace{0.3em}
215
216\begin{quote}
217\small\noindent\textbf{Abstrakt.}
218Enhver kreativ kodningsplatform definerer en kerne-API---et lille sæt funktioner, hvorigennem programmer ser verden og tegner på den. Processings \texttt{setup()}/\texttt{draw()} med globale tegneprimitiver (\texttt{background()}, \texttt{stroke()}, \texttt{ellipse()}) etablerede et mønster i 2001, der har formet to årtiers kreative kodningsværktøjer. p5.js bragte denne model til browseren i 2014, bevarede API-overfladen mens den tilpassede sig JavaScript og DOM'en. \ac{} (AC), påbegyndt i 2021, bærer Processings tænkning i sin kerne, mens den udvider modellen på flere strukturelle måder: den udvider to-funktions livscyklussen til fem (\texttt{boot}, \texttt{paint}, \texttt{act}, \texttt{sim}, \texttt{leave}), eliminerer global tilstand til fordel for destruktureret API-injektion, adskiller simulation fra rendering ved forskellige tick-rater og gør hvert program URL-adresserbart uden byggetrin. Denne artikel sporer, hvordan Processings idéer lever inde i AC piece-API'en, sammenligner livscyklusmodellerne, tegneprimitiver, inputhåndtering og tilstandsstyringsstrategier på tværs af Design By Numbers, Processing, p5.js og AC. Vi argumenterer for, at AC API-designet---med Processings immediate-mode grafikmodel som fundament---udvider \emph{skitsebogs}-metaforen (skriv, kør, kassér) til en \emph{instrument}-metafor (boot, spil, øv, vend tilbage).
219\end{quote}
220\vspace{0.5em}
221}]
222
223% ============ 1. INTRODUKTION ============
224
225\section{Introduktion}
226
227Historien om kreative kodnings-API'er er en historie om at beslutte, hvad programmøren skal sige først. I Design By Numbers~\citep{maeda2001dbn} var den første udsagn en koordinat og en gråtoneværdi: \texttt{Paper 50}. I Processing~\citep{reas2003processing} var det \texttt{size(200, 200)} inde i \texttt{setup()}. I p5.js~\citep{mccarthy2015p5js} var det \texttt{createCanvas(400, 400)}. I \ac{} siger programmøren intet om lærredet overhovedet---køretiden leverer \texttt{screen.width} og \texttt{screen.height} som givne fakta, og den første meningsfulde udsagn er typisk \texttt{wipe()}, der rydder skærmen for at begynde at male.
228
229Disse er ikke vilkårlige forskelle. Hver afspejler en beslutning om, hvad platformen antager versus hvad programmøren må specificere, og disse beslutninger akkumulerer til fundamentalt forskellige relationer mellem forfatter og maskine. Denne artikel sporer API-slægtskabet fra Processing gennem p5.js til AC og undersøger hver overgang som et sæt designtræk: hvad der blev beholdt, hvad der blev ændret, og hvad ændringen indebærer.
230
231Bidraget er tredelt: (1) en detaljeret teknisk sammenligning af livscyklusmodellerne, tegne-API'erne, inputsystemerne og tilstandsstyringsstrategierne i Processing, p5.js og AC; (2) en analyse af designrationalet bag AC's afvigelser fra Processing-modellen; og (3) et argument for, at AC piece-API'en legemliggør et skift fra skitsebogsmetaforen til det, vi kalder \emph{instrumentmetaforen}---en model, hvor forholdet mellem programmør og program er vedvarende, performativt og praksisbaseret snarere end eksplorativt og engangs.
232
233% ============ 2. PROCESSING-MODELLEN ============
234
235\section{Processing-modellen (2001)}
236\label{sec:processing}
237
238Processing~\citep{reas2007processing} blev designet som en ``software-skitsebog'' for billedkunstnere. Dets API er centreret om to livscyklusfunktioner og et bibliotek af globale tegneprimitiver.
239
240\subsection{Livscyklus: \texttt{setup()} og \texttt{draw()}}
241
242\begin{lstlisting}[style=processingstyle,caption={Minimal Processing-skitse.}]
243void setup() {
244 size(400, 400);
245 background(0);
246}
247
248void draw() {
249 stroke(255);
250 ellipse(mouseX, mouseY, 20, 20);
251}
252\end{lstlisting}
253
254\texttt{setup()} kører én gang; \texttt{draw()} kører hvert frame med standard 60fps. Denne to-funktions model er Processings mest indflydelsesrige designbeslutning. Den reducerer det kognitive overhead ved animation fra at styre en renderingsløkke til at udfylde to tomme felter: ``hvad sker én gang?'' og ``hvad sker hvert frame?''
255
256Modellen er bevidst minimal. Der er ingen eksplicit \texttt{input()}-funktion---muse- og tastaturtilstand er tilgængelig som globale variabler (\texttt{mouseX}, \texttt{mouseY}, \texttt{key}, \texttt{keyCode}), der opdateres automatisk. Hændelses-callbacks (\texttt{mousePressed()}, \texttt{keyPressed()}) eksisterer, men er valgfrie supplementer, ikke påkrævede indgangspunkter.
257
258\subsection{Tegneprimitiver}
259
260Processings tegne-API bruger en \emph{tilstandsbaseret pipeline}-model arvet fra PostScript og OpenGL: tilstandssættende kald (\texttt{stroke()}, \texttt{fill()}, \texttt{strokeWeight()}) modificerer en vedvarende grafikkontekst, og formkald (\texttt{ellipse()}, \texttt{rect()}, \texttt{line()}) renderer med den kontekst. Konteksten vedbliver på tværs af frames, medmindre den eksplicit nulstilles.
261
262\begin{lstlisting}[style=processingstyle,caption={Tilstandsbaseret tegnekontekst.}]
263void draw() {
264 fill(255, 0, 0); // Sæt fyld: rød
265 stroke(0); // Sæt streg: sort
266 strokeWeight(3); // Sæt bredde: 3px
267 ellipse(100, 100, 50, 50); // Bruger ovenstående
268 rect(200, 100, 50, 50); // Bruger også ovenstående
269 // Tilstand vedbliver til næste frame
270}
271\end{lstlisting}
272
273Denne tilstandsvedvarenhed er både kraftfuld (mindre kode for ensartede stile) og fejlbehæftet (glemt tilstand lækker på tværs af frames). Processing adresserer dette med \texttt{pushStyle()}/\texttt{popStyle()} og \texttt{pushMatrix()}/\texttt{popMatrix()}, men disse er ekspertværktøjer.
274
275\subsection{Globalt scope}
276
277Alle Processing-programmer deler et enkelt globalt navnerum. Variabler erklæret uden for \texttt{setup()} og \texttt{draw()} er tilgængelige overalt. Tegnefunktionerne (\texttt{line()}, \texttt{ellipse()}, \texttt{background()}) er globale. Inputvariabler (\texttt{mouseX}, \texttt{mouseY}) er globale. Dette eliminerer behovet for at forstå scope, imports eller dependency injection---kritisk for begyndere---men gør programmer umulige at komponere eller isolere.
278
279% ============ 3. P5.JS-OVERGANGEN ============
280
281\section{p5.js-overgangen (2014)}
282\label{sec:p5js}
283
284p5.js~\citep{mccarthy2015p5js} er en JavaScript-reimplementering af Processing. Dets primære bidrag er at bringe Processing-modellen til browseren, men porten krævede adskillige tilpasninger.
285
286\subsection{Bevarelse af livscyklus}
287
288\begin{lstlisting}[style=p5style,caption={Minimal p5.js-skitse.}]
289function setup() {
290 createCanvas(400, 400);
291}
292
293function draw() {
294 background(220);
295 ellipse(mouseX, mouseY, 50, 50);
296}
297\end{lstlisting}
298
299\texttt{setup()}/\texttt{draw()}-modellen er bevaret nøjagtigt. Den kognitive model er identisk: to funktioner, globale tegneprimitiver, automatisk animationsløkke. Denne kontinuitet er bevidst---p5.js sigter mod at være Processing for webbet, ikke et nyt sprog.
300
301\subsection{Oprettelse af lærred}
302
303Den mest synlige ændring er \texttt{createCanvas()}, der erstatter \texttt{size()}. Dette er ikke kosmetisk: i Processing konfigurerer \texttt{size()} applikationsvinduet; i p5.js opretter \texttt{createCanvas()} et HTML \texttt{<canvas>}-element inden for DOM'en. Skitsen må forhandle med den eksisterende side snarere end at eje hele skærmen.
304
305\subsection{Instance mode}
306
307p5.js introducerer en vigtig flugtvej fra det globale navnerum: \emph{instance mode}.
308
309\begin{lstlisting}[style=p5style,caption={p5.js instance mode.}]
310const sketch = (p) => {
311 p.setup = () => {
312 p.createCanvas(400, 400);
313 };
314 p.draw = () => {
315 p.background(220);
316 p.ellipse(p.mouseX, p.mouseY, 50, 50);
317 };
318};
319new p5(sketch);
320\end{lstlisting}
321
322Instance mode pakker alle API-funktioner bag et navnerum (\texttt{p.}), hvilket tillader flere skitser på én side og undgår global forurening. Dog skrives det meste p5.js-kode i global tilstand, og instance mode mødes typisk kun ved indlejring af skitser i større applikationer. Præfiks-notationen (\texttt{p.ellipse} vs.\ \texttt{ellipse}) øger ordrigdommen og reducerer den ``bare skriv''-kvalitet, der gør Processing indbydende.
323
324\subsection{Hvad der ændrede sig, hvad der ikke gjorde}
325
326p5.js bevarede: to-funktions livscyklussen, globale tegneprimitiver, tilstandsbaseret grafikkontekst, frame-baseret animation og ``skitse''-identiteten. Det tilpassede: lærredsoprettelse til DOM'en, renderer-valg (2D/WebGL), hændelseshåndtering til browserhændelser og tilføjede instance mode til komposition. Det adresserede ikke: sammenblanding af simulation og rendering, manglen på struktureret inputhåndtering eller enkelt-fil-isolationsproblemet.
327
328% ============ 4. AC PIECE-API'EN ============
329
330\section{AC Piece-API'en (2021--)}
331\label{sec:ac}
332
333\ac{}'s piece-API~\citep{scudder2026ac} er bygget på Processings kerneidéer---immediate-mode grafik, enkelt-fil programmer, livscyklusfunktioner---og udvider dem omkring fem hensyn i stedet for to.
334
335\subsection{Fem livscyklusfunktioner}
336
337\begin{lstlisting}[style=acjsstyle,caption={Minimalt AC piece.}]
338function boot({ screen, params }) {
339 // Kører én gang ved indlæsning
340}
341
342function paint({ wipe, ink, line, screen }) {
343 wipe("navy");
344 ink("pink").circle(
345 screen.width / 2,
346 screen.height / 2,
347 50
348 );
349}
350
351function act({ event: e }) {
352 if (e.is("keyboard:down:space")) {
353 // Håndtér mellemrumstast
354 }
355}
356
357function sim() {
358 // Opdatér tilstand ved 120fps
359}
360
361export { boot, paint, act, sim };
362\end{lstlisting}
363
364De fem funktioner er:
365
366\begin{itemize}
367 \item \texttt{boot(\$api)} --- kører én gang, når piecet indlæses. Udvider Processings \texttt{setup()}, hvor skærmen leveres af køretiden snarere end konfigureres af programmøren.
368 \item \texttt{paint(\$api)} --- kører hvert frame, der kræver rendering. Viderefører \texttt{draw()}'s immediate-mode model, men er rent visuelt: ingen logik, ingen tilstandsmutation (ved konvention).
369 \item \texttt{act(\$api)} --- kaldes én gang per inputhændelse. Konsoliderer Processings hændelses-callbacks (\texttt{mousePressed()}, \texttt{keyPressed()}) til ét samlet indgangspunkt.
370 \item \texttt{sim(\$api)} --- kører med faste 120Hz, potentielt flere gange per renderet frame. Har ingen ækvivalent i Processing; nærmeste analogi er fast-tidstrin spilsløjfen~\citep{nystrom2014game}.
371 \item \texttt{leave(\$api)} --- oprydning ved afslutning. Ingen ækvivalent i Processing, hvor skitser simpelthen terminerer.
372\end{itemize}
373
374Hver funktion er valgfri. Et piece, der kun eksporterer \texttt{paint}, er et gyldigt, fungerende program.
375
376\subsection{API-injektion via destrukturering}
377
378Den mest strukturelt betydningsfulde udvidelse af Processing-modellen er, at \textbf{ingen API-funktioner eksisterer i det globale scope}. Enhver funktion, piecet bruger, modtages som en parameter:
379
380\begin{lstlisting}[style=acjsstyle,caption={API-destrukturering i AC.}]
381function paint({ wipe, ink, line, box,
382 circle, screen, num }) {
383 wipe(0, 0, 30);
384 ink(255, 100, 180);
385 const cx = num.lerp(0, screen.width, 0.5);
386 circle(cx, screen.height / 2, 40);
387}
388\end{lstlisting}
389
390Dette design har flere konsekvenser:
391
392\begin{enumerate}
393 \item \textbf{Ingen global forurening.} Modulniveau-variabler er piece-tilstand; API-funktioner er parametre. Der er intet omgivende navnerum at kollidere med.
394 \item \textbf{Selvdokumenterende imports.} Destruktureringsmønstret øverst i hver funktion erklærer nøjagtigt, hvilke API-overflader funktionen bruger, og fungerer som et inline afhængighedsmanifest.
395 \item \textbf{Komponerbarhed.} Flere pieces kan sameksistere i den samme JavaScript-kontekst uden API-kollisioner, hvilket muliggør platformens piece-skiftning og indlejringsmekanismer.
396 \item \textbf{Opdagelighed.} Autokomplettering i editorer virker på det destrukturerede parameterobjekt og giver en naturlig måde at udforske API'en.
397\end{enumerate}
398
399Dette er p5.js instance mode-mønstret ført til sin konklusion: i stedet for at præfikse hvert kald med \texttt{p.}, destrukturerer programmøren nøjagtigt de funktioner, de har brug for, én gang, ved funktionssignaturen.
400
401\subsection{Adskillelse af simulation og rendering}
402\label{sec:simsep}
403
404Processings \texttt{draw()} sammenblander to hensyn: opdatering af tilstand og rendering af pixels. Dette virker for simple skitser, men skaber problemer i takt med stigende kompleksitet: fysiksimulationer bundet til billedrate, inputlatenstid koblet til renderingsomkostninger og vanskelighed ved at adskille ``hvad der skete'' fra ``hvordan det ser ud.''
405
406AC adskiller disse eksplicit:
407
408\begin{itemize}
409 \item \texttt{sim()} kører med faste 120Hz, uafhængigt af skærmens opdateringshastighed. På en 60Hz-skærm kører \texttt{sim()} to gange per \texttt{paint()}-kald. På en 144Hz-skærm justeres forholdet tilsvarende.
410 \item \texttt{paint()} kører med skærmens opdateringshastighed (begrænset til ca. 165fps) og er kun ansvarlig for at rendere den aktuelle tilstand.
411 \item \texttt{act()} kører én gang per inputhændelse, umiddelbart når hændelsen ankommer.
412\end{itemize}
413
414Denne trevejsopsplitning afspejler arkitekturen i moderne spilmotorer~\citep{nystrom2014game}: et fast opdateringstick for deterministisk logik, et variabelt render-tick for jævn visning og en hændelseskø for input. Forskellen er, at AC eksponerer denne arkitektur som en førsteklasses API i stedet for at skjule den bag et framework.
415
416\subsection{Samlet hændelseshåndtering}
417
418Processing distribuerer inputhåndtering på tværs af globale variabler og valgfrie callbacks:
419
420\begin{lstlisting}[style=processingstyle]
421// Processing: spredt inputmodel
422void draw() {
423 if (mousePressed) { /* poll tilstand */ }
424}
425void mousePressed() { /* callback */ }
426void keyPressed() { /* callback */ }
427void mouseDragged() { /* callback */ }
428\end{lstlisting}
429
430AC konsoliderer al input i \texttt{act()} med et strengbaseret hændelsesmatchningsystem:
431
432\begin{lstlisting}[style=acjsstyle]
433function act({ event: e, pen }) {
434 if (e.is("touch")) { }
435 if (e.is("draw")) { }
436 if (e.is("lift")) { }
437 if (e.is("keyboard:down:a")) { }
438 if (e.is("keyboard:down:space")){ }
439 if (e.is("gamepad:a")) { }
440 if (e.is("reframed")) { }
441}
442\end{lstlisting}
443
444Mønstret \texttt{event.is()} giver en ensartet grænseflade på tværs af inputmodaliteter (berøring, mus, tastatur, gamepad, MIDI, håndstyring) gennem en enkelt funktion. Hændelsesstrenge er hierarkiske (\texttt{keyboard:down:a}) og kan matches på ethvert specificitetsniveau. Dette erstatter den kombinatoriske eksplosion af Processing-callbacks med en enkelt, filtrerbar strøm.
445
446\subsection{Tegneprimitiver: tilstandsløse som standard}
447
448Processing og p5.js bruger en tilstandsbaseret grafikkontekst, hvor \texttt{fill()}, \texttt{stroke()} og transformationskald vedvarer, indtil de eksplicit ændres. AC inverterer dette: \texttt{ink()}-funktionen sætter farve for det \emph{umiddelbart følgende} tegnekald og returnerer API-objektet til kædekobling:
449
450\begin{lstlisting}[style=acjsstyle]
451function paint({ wipe, ink, line, circle }) {
452 wipe("black");
453 ink("red").circle(50, 50, 20);
454 ink("blue").line(0, 0, 100, 100);
455 // Ingen tilstandslæk mellem kald
456}
457\end{lstlisting}
458
459\texttt{ink()}-retur-og-kæde-mønstret gør farve-form-par visuelt atomare: hver tegneoperation er et selvstændigt udtryk snarere end en sekvens af kontekstmutationer. Dette eliminerer den fejlklasse, hvor glemte \texttt{fill()}- eller \texttt{stroke()}-kald fra et tidligere frame (eller en tidligere funktion) bløder ind i urelateret tegning.
460
461\texttt{wipe()}-funktionen erstatter Processings \texttt{background()}, med et kortere, mere aktivt verbum. Denne navngivning er bevidst: ``wipe'' antyder en fysisk handling (at tørre en overflade) snarere end en egenskabsindstilling.
462
463\subsection{Ingen lærredskonfiguration}
464
465I Processing er den første linje i \texttt{setup()} typisk \texttt{size(w, h)}. I p5.js er det \texttt{createCanvas(w, h)}. I AC er der intet ækvivalent kald. Køretiden leverer lærredet i enhedens native opløsning, og pieces modtager \texttt{screen.width} og \texttt{screen.height} som skrivebeskyttede egenskaber.
466
467Dette afspejler en mobil-først designfilosofi: på telefoner og tablets er den ``korrekte'' lærredsstørrelse enhedens skærm. At tillade programmøren at specificere dimensioner skaber en uoverensstemmelse mellem det faste lærred og den variable viewport. AC eliminerer denne uoverensstemmelse ved at gøre lærredet responsivt som standard.
468
469% ============ 5. API-OVERFLADE SAMMENLIGNING ============
470
471\section{API-overfladesammenligning}
472\label{sec:comparison}
473
474Tabel~\ref{tab:lifecycle} sammenligner livscyklusmodellerne. Tabel~\ref{tab:drawing} sammenligner tegneprimitiver.
475
476\begin{table}[h]
477\small
478\centering
479\begin{tabularx}{\columnwidth}{lXXX}
480\toprule
481 & \textbf{Processing} & \textbf{p5.js} & \textbf{AC} \\
482\midrule
483Init & \texttt{setup()} & \texttt{setup()} & \texttt{boot(\$)} \\
484Render & \texttt{draw()} & \texttt{draw()} & \texttt{paint(\$)} \\
485Logik & (i draw) & (i draw) & \texttt{sim(\$)} \\
486Input & callbacks & callbacks & \texttt{act(\$)} \\
487Oprydning & --- & \texttt{remove()} & \texttt{leave(\$)} \\
488\midrule
489Renderrate & 60fps & 60fps & skærm Hz \\
490Logikrate & 60fps & 60fps & 120fps fast \\
491Scope & globalt & globalt/inst. & injiceret \\
492\bottomrule
493\end{tabularx}
494\caption{Livscyklussammenligning. \texttt{\$} betegner destruktureret API-injektion.}
495\label{tab:lifecycle}
496\end{table}
497
498\begin{table}[h]
499\small
500\centering
501\begin{tabularx}{\columnwidth}{lXX}
502\toprule
503\textbf{Processing/p5} & \textbf{AC} & \textbf{Noter} \\
504\midrule
505\texttt{background()} & \texttt{wipe()} & Verbum, ikke egenskab \\
506\texttt{fill() + stroke()} & \texttt{ink()} & Samlet, kædebar \\
507\texttt{ellipse()} & \texttt{circle()} & Opkaldt efter form \\
508\texttt{rect()} & \texttt{box()} & Kortere navn \\
509\texttt{line()} & \texttt{line()} & Uændret \\
510\texttt{point()} & \texttt{plot()} & Graf-metafor \\
511\texttt{text()} & \texttt{write()} & Aktivt verbum \\
512--- & \texttt{flood()} & Fyld region \\
513--- & \texttt{paste()} & Buffer-kompositing \\
514--- & \texttt{form()} & 3D-rendering \\
515\bottomrule
516\end{tabularx}
517\caption{Sammenligning af tegneprimitiver.}
518\label{tab:drawing}
519\end{table}
520
521\subsection{Navngivningsfilosofi}
522
523Processings API-navne er beskrivende substantiver og adjektiver: \texttt{background}, \texttt{ellipse}, \texttt{rect}, \texttt{stroke}, \texttt{fill}. De beskriver \emph{hvad} der sættes eller tegnes. AC's navne er aktive verber: \texttt{wipe}, \texttt{ink}, \texttt{plot}, \texttt{write}, \texttt{flood}, \texttt{paste}. De beskriver \emph{hvad programmøren gør}---fysiske handlinger udført på en overflade.
524
525Dette skift fra beskrivende til imperativ navngivning stemmer overens med instrumentmetaforen: et instruments grænseflade forstås gennem verber (tryk, pust, slå, pluk), ikke substantiver. AC-API'en læses som en sekvens af handlinger: ``tør skærmen, blæk den pink, tegn en cirkel, skriv noget tekst.''
526
527\subsection{Farvemodel}
528
529Processing bruger separate \texttt{fill()}- og \texttt{stroke()}-kald, der hver accepterer RGB-, HSB- eller hex-værdier. Fyld/streg-distinktionen afspejler vektorgrafik (SVG, PostScript), hvor former har indre farve og grænsefarve.
530
531AC bruger et enkelt \texttt{ink()}-kald, der sætter farve for alle efterfølgende operationer. Der er ingen fyld/streg-distinktion: en \texttt{circle()} er fyldt eller streget baseret på dens parametre, ikke på omgivende kontekst. \texttt{ink()}-funktionen accepterer:
532
533\begin{itemize}
534 \item RGB-værdier: \texttt{ink(255, 100, 50)}
535 \item Navngivne farver: \texttt{ink("pink")}, \texttt{ink("navy")}
536 \item Gråtone: \texttt{ink(128)}
537 \item Alfa: \texttt{ink(255, 0, 0, 128)}
538\end{itemize}
539
540Navngivne farver er et betydningsfuldt brugervenligheds-valg for begyndere. Hvor Processing kræver \texttt{fill(255, 192, 203)} for pink, accepterer AC \texttt{ink("pink")}. Det navngivne farveordforråd er bevidst lille og evokativt, tættere på en malerkasse end en farvevælger.
541
542% ============ 6. TILSTANDSSTYRING ============
543
544\section{Tilstandsstyring}
545\label{sec:state}
546
547\subsection{Processing: globale variabler}
548
549\begin{lstlisting}[style=processingstyle]
550int x = 100;
551int y = 100;
552
553void draw() {
554 background(0);
555 x += 1;
556 ellipse(x, y, 20, 20);
557}
558\end{lstlisting}
559
560Tilstand i Processing lever i globale variabler. Dette er simpelt, men har velkendte problemer: al tilstand er muterbar overalt, der er ingen indkapsling, og programtilstand er umulig at skelne fra API-tilstand.
561
562\subsection{AC: modulniveau-closures}
563
564\begin{lstlisting}[style=acjsstyle]
565let x = 100;
566let y = 100;
567
568function sim() {
569 x += 1;
570}
571
572function paint({ wipe, ink, circle }) {
573 wipe(0);
574 ink(255).circle(x, y, 20);
575}
576
577export { sim, paint };
578\end{lstlisting}
579
580AC pieces er ES-moduler. Variabler erklæret på modulniveau er private for piecet---usynlige for køretiden, andre pieces og det globale scope. \texttt{export}-erklæringen gør kun livscyklusfunktionerne synlige. Dette er ikke en konvention håndhævet af dokumentation; det er en garanti fra JavaScript-modulsystemet.
581
582Adskillelsen af tilstandsmutation (\texttt{sim}) fra tilstandsrendering (\texttt{paint}) opmuntrer til en disciplin, hvor \texttt{paint} er en ren funktion af modultilstand---den læser variabler og tegner, men modificerer dem ikke. Dette håndhæves ikke, men API-strukturen gør det til det naturlige mønster.
583
584% ============ 7. SLÆGTSKABET ============
585
586\section{Slægtskabet}
587\label{sec:genealogy}
588
589\subsection{Design By Numbers (1999)}
590
591Maedas Design By Numbers~\citep{maeda2001dbn} introducerede kerneindsigten: et programmeringsmiljø til visuel output, med den simplest mulige API. DBN havde ingen animationsløkke---programmer kørte én gang, fra top til bund. Primitivsættet var minimalt: \texttt{Paper} (baggrund), \texttt{Pen} (stregbredde), \texttt{Line}, \texttt{Set} (pixel) og kontrolflow. Hele sproget kunne læres på en eftermiddag.
592
593AC arver DBN's minimalisme i navngivning (korte, aktive verber) og dets overbevisning om, at API'en bør være udtømmende lærbar.
594
595\subsection{Processing (2001)}
596
597Processing~\citep{reas2003processing} tilføjede, hvad DBN manglede: animation (\texttt{draw()}-løkke), interaktion (\texttt{mouseX/Y}) og et rigere primitivsæt. Det tilføjede også, hvad DBN bevidst undgik: tilstand (grafikkonteksten), et standardbibliotek (matematik, typografi, billedindlæsning) og et kompileringstrin (Java). Processings største innovation var ikke nogen enkelt funktion, men \texttt{setup()}/\texttt{draw()}-parret: det simplest mulige udtryk for interaktiv animation.
598
599AC arver livscyklusfunktionsmodellen, men opdeler \texttt{draw()} i tre hensyn (\texttt{paint}, \texttt{sim}, \texttt{act}).
600
601\subsection{p5.js (2014)}
602
603p5.js~\citep{mccarthy2015p5js} bragte Processing til browseren og gjorde skitser øjeblikkeligt delbare via URL. Dette var en forudsætning for AC: browseren som kreativ platform. p5.js introducerede også instance mode, der forvarslede AC's API-injektionsmønster.
604
605AC arver browser-native-antagelsen og delbarhedsprincippet (hvert piece er en URL), men erstatter bibliotek-i-en-side-modellen med en fuld køretid: pieces inkluderer ikke et \texttt{<script>}-tag; de indlæses af platformen.
606
607\subsection{openFrameworks (2005)}
608
609openFrameworks~\citep{openframeworks2005} brugte en lignende livscyklus (\texttt{setup()}, \texttt{update()}, \texttt{draw()}) men i C++, med adskillelse af opdateringslogik fra rendering. AC's \texttt{sim()}/\texttt{paint()}-opsplitning er tættere på denne model end på Processings samlede \texttt{draw()}.
610
611\subsection{Instrumentvendingen}
612
613Slægtskabet kan opsummeres som en række adskillelser:
614
615\begin{enumerate}
616 \item \textbf{DBN}: engangskørsel (ingen animationsløkke).
617 \item \textbf{Processing}: init + render (\texttt{setup} + \texttt{draw}).
618 \item \textbf{openFrameworks}: init + opdatering + render.
619 \item \textbf{AC}: init + input + opdatering + render + oprydning (\texttt{boot} + \texttt{act} + \texttt{sim} + \texttt{paint} + \texttt{leave}).
620\end{enumerate}
621
622Hvert trin adskiller hensyn, der tidligere var sammenblandet. AC's fem-funktions model er den mest fuldstændige nedbrydning af det interaktive programs livscyklus i navngivne, enkeltansvars-indgangspunkter. Resultatet ligner perception-handling-cyklussen i legemliggjort kognition~\citep{varela1991embodied}: percipér (\texttt{act}), tænk (\texttt{sim}), handl (\texttt{paint}), og de yderligere bogstøtter af fødsel (\texttt{boot}) og død (\texttt{leave}).
623
624% ============ 8. GENNEMARBEJDET EKSEMPEL ============
625
626\section{Gennemarbejdet eksempel: En hoppende bold}
627\label{sec:example}
628
629For at konkretisere sammenligningen implementerer vi en hoppende bold i alle tre systemer.
630
631\subsection{Processing}
632
633\begin{lstlisting}[style=processingstyle]
634float x = 200, y = 200;
635float vx = 3, vy = 2;
636
637void setup() {
638 size(400, 400);
639}
640
641void draw() {
642 background(0);
643 x += vx; y += vy;
644 if (x < 0 || x > width) vx *= -1;
645 if (y < 0 || y > height) vy *= -1;
646 fill(255, 100, 180);
647 noStroke();
648 ellipse(x, y, 30, 30);
649}
650\end{lstlisting}
651
652Logik og rendering er sammenflettet i \texttt{draw()}. Tilstandsmutation (\texttt{x += vx}), grænsetjek og tegning deler alle én funktion.
653
654\subsection{p5.js}
655
656\begin{lstlisting}[style=p5style]
657let x = 200, y = 200;
658let vx = 3, vy = 2;
659
660function setup() {
661 createCanvas(400, 400);
662}
663
664function draw() {
665 background(0);
666 x += vx; y += vy;
667 if (x < 0 || x > width) vx *= -1;
668 if (y < 0 || y > height) vy *= -1;
669 fill(255, 100, 180);
670 noStroke();
671 ellipse(x, y, 30, 30);
672}
673\end{lstlisting}
674
675Strukturelt identisk med Processing. De eneste ændringer er syntaktiske: \texttt{let} vs.\ \texttt{float}, \texttt{createCanvas} vs.\ \texttt{size}.
676
677\subsection{AC}
678
679\begin{lstlisting}[style=acjsstyle]
680let x, y, vx = 3, vy = 2;
681
682function boot({ screen }) {
683 x = screen.width / 2;
684 y = screen.height / 2;
685}
686
687function sim({ screen }) {
688 x += vx; y += vy;
689 if (x < 0 || x > screen.width) vx *= -1;
690 if (y < 0 || y > screen.height) vy *= -1;
691}
692
693function paint({ wipe, ink, circle }) {
694 wipe(0);
695 ink(255, 100, 180).circle(x, y, 15);
696}
697
698export { boot, sim, paint };
699\end{lstlisting}
700
701Hensynene er adskilt: \texttt{boot} initialiserer tilstand relativt til den faktiske skærm, \texttt{sim} opdaterer fysik ved 120Hz (hvilket sikrer konsistent opførsel på tværs af skærmenes opdateringshastigheder), og \texttt{paint} renderer uden at modificere tilstand. \texttt{ink().circle()}-kæden erstatter tre linjer (\texttt{fill}, \texttt{noStroke}, \texttt{ellipse}).
702
703% ============ 9. DESIGNRATIONALE ============
704
705\section{Designrationale}
706\label{sec:rationale}
707
708\subsection{Hvorfor fem funktioner?}
709
710Fem-funktions modellen er ikke motiveret af softwareingeniør-stringens (``adskillelse af hensyn'' som dogme) men af instrumentmetaforen. Et musikinstrument har distinkte faser: du tager det op (boot), du lytter og reagerer (act), du tænker over, hvad der kommer næst (sim), du spiller (paint), og til sidst lægger du det fra dig (leave). Disse er ikke udskiftelige øjeblikke---du stemmer ikke instrumentet under optræden, og du optræder ikke, mens du lægger det væk. Livscyklusfunktionerne formaliserer disse distinktioner.
711
712\subsection{Hvorfor injicere API'en?}
713
714Globale API'er er praktiske for begyndere, men skaber en implicit afhængighed af platformen. En Processing-skitse kan ikke forstås uden at vide, at \texttt{ellipse()} er en Processing-funktion, ikke en brugerfunktion. AC's destruktureringsmønster gør afhængigheden eksplicit: hvis \texttt{circle} optræder i funktionskroppen, optræder den i funktionssignaturen. Dette er det samme designprincip bag ES-modulimports, anvendt på funktionsniveau.
715
716Den praktiske fordel er hot-reloading: fordi pieces ikke fanger globale referencer, kan køretiden erstatte API-objektet mellem genindlæsninger uden at ugyldiggøre piecets closures.
717
718\subsection{Hvorfor 120Hz simulation?}
719
720Processings \texttt{draw()} kører med skærmraten (typisk 60fps). Det betyder, at fysiksimulationer, animationstiming og inputbehandling alle kører med samme rate som pixel-output. På en 144Hz-skærm kører en Processing-skitse 2,4$\times$ hurtigere; på en 30Hz-skærm kører den med halv hastighed.
721
722AC afkobler simulation fra visning ved at køre \texttt{sim()} med faste 120Hz. Dette sikrer deterministisk opførsel: en hoppende bold bevæger sig med samme hastighed uanset skærmens opdateringshastighed. 120Hz-raten blev valgt som et multiplum af almindelige skærmrater (60, 120) og en rimelig øvre grænse for input-responsivitet.
723
724\subsection{Hvorfor ingen lærredsstørrelse?}
725
726At kræve \texttt{size()} eller \texttt{createCanvas()} antager, at programmøren kender (og bekymrer sig om) outputopløsningen. På desktop er dette rimeligt. På mobil---AC's primære mål---er det en kilde til friktion: den ``rigtige'' størrelse afhænger af enheden, orienteringen og pixeltætheden, som programmøren ikke bør behøve at håndtere. AC leverer skærmen som en given størrelse, som et lærred der allerede er strakt og grundet.
727
728% ============ 10. UDVIDET LIVSCYKLUS ============
729
730\section{Udvidet livscyklus}
731\label{sec:extended}
732
733Ud over de fem kernefunktioner kan AC pieces eksportere yderligere livscyklus-hooks:
734
735\begin{itemize}
736 \item \texttt{beat(\$api)} --- kaldes én gang per metronom-tick. BPM sættes via \texttt{sound.bpm}. Dette har ingen ækvivalent i Processing; det afspejler AC's orientering mod musikalske anvendelser.
737 \item \texttt{preview(\$api)} --- renderer et statisk thumbnailbillede for piecet. Bruges i piece-lister og social deling.
738 \item \texttt{icon(\$api)} --- renderer et favicon til browserfanen.
739 \item \texttt{meta()} --- returnerer \texttt{\{title, desc\}} metadata til Open Graph-tags.
740 \item \texttt{receive(event)} --- håndterer beskeder fra andre pieces eller systemet, hvilket muliggør inter-piece-kommunikation.
741\end{itemize}
742
743\texttt{beat()}-funktionen er særligt bemærkelsesværdig. Den ophøjer rytmisk timing fra en funktion, programmøren selv må implementere (via \texttt{millis()} i Processing), til en førsteklasses livscyklushændelse. Dette er en API-niveau-erklæring om, at musik og rytme er kernebrugsscenarier, ikke eftertanker.
744
745% ============ 11. KONKLUSION ============
746
747\section{Konklusion}
748\label{sec:conclusion}
749
750Processings kerneindsigt---at et programmeringsmiljø for kreativt arbejde bør levere en livscyklus, ikke bare et sprog---lever i centrum af hvert AC piece. Vejen fra \texttt{setup()}/\texttt{draw()} til \texttt{boot()}/\texttt{paint()}/\texttt{act()}/\texttt{sim()}/\texttt{leave()} er ikke en afvigelse fra Processing, men et argument for, hvad Processings model er i stand til, når den udvides yderligere.
751
752Processing beviste, at \texttt{setup()} + \texttt{draw()} var nok til at gøre animation tilgængelig. AC piece-API'en argumenterer for, at den samme immediate-mode, livscyklusdrevne tilgang---når den nedbrydes i fem funktioner i stedet for to---kan understøtte ikke bare skitsering, men \emph{øvelse}: at vende tilbage til det samme piece, forfine det, optræde med det, opbygge flydende beherskelse over tid.
753
754Skitsebogsmetaforen (skriv, kør, kassér) og instrumentmetaforen (boot, spil, øv, vend tilbage) er ikke modsatte. De er punkter på det samme kontinuum. Processing viste, at kontinuummet eksisterer. AC argumenterer for, at det strækker sig længere, end vi troede---at \texttt{setup()} + \texttt{draw()} var begyndelsen på en idé, hvis fulde form kræver \texttt{boot} + \texttt{act} + \texttt{sim} + \texttt{paint} + \texttt{leave}.
755
756API'en er instrumentet. Processing er dens kerne. Hvordan API'en nedbryder handlingen at programmere, bestemmer, hvad der skabes.
757
758\vspace{0.5em}\noindent\textit{Oversat fra engelsk. Originalversion tilgængelig på \url{https://papers.aesthetic.computer}}
759
760\bibliographystyle{plainnat}
761\bibliography{references}
762
763\end{document}