% !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={Fra setup() til boot(): Processing i kernen af Piece-API'en}, } % === 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{Arbejdsudkast --- ikke til 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}} \begin{document} % ============ TITLE BLOCK ============ \twocolumn[{% \begin{center} {\acbold\fontsize{22pt}{26pt}\selectfont\color{acdark} Fra \texttt{setup()} til \texttt{boot()}}\par \vspace{0.2em} {\aclight\fontsize{11pt}{13pt}\selectfont\color{acpink} Processing i kernen af Piece-API'en}\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{[ arbejdsudkast --- ikke til citation ]}} \end{center} \vspace{0.3em} \begin{quote} \small\noindent\textbf{Abstrakt.} Enhver 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). \end{quote} \vspace{0.5em} }] % ============ 1. INTRODUKTION ============ \section{Introduktion} Historien 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. Disse 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. Bidraget 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. % ============ 2. PROCESSING-MODELLEN ============ \section{Processing-modellen (2001)} \label{sec:processing} Processing~\citep{reas2007processing} blev designet som en ``software-skitsebog'' for billedkunstnere. Dets API er centreret om to livscyklusfunktioner og et bibliotek af globale tegneprimitiver. \subsection{Livscyklus: \texttt{setup()} og \texttt{draw()}} \begin{lstlisting}[style=processingstyle,caption={Minimal Processing-skitse.}] void setup() { size(400, 400); background(0); } void draw() { stroke(255); ellipse(mouseX, mouseY, 20, 20); } \end{lstlisting} \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?'' Modellen 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. \subsection{Tegneprimitiver} Processings 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. \begin{lstlisting}[style=processingstyle,caption={Tilstandsbaseret tegnekontekst.}] void draw() { fill(255, 0, 0); // Sæt fyld: rød stroke(0); // Sæt streg: sort strokeWeight(3); // Sæt bredde: 3px ellipse(100, 100, 50, 50); // Bruger ovenstående rect(200, 100, 50, 50); // Bruger også ovenstående // Tilstand vedbliver til næste frame } \end{lstlisting} Denne 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. \subsection{Globalt scope} Alle 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. % ============ 3. P5.JS-OVERGANGEN ============ \section{p5.js-overgangen (2014)} \label{sec:p5js} p5.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. \subsection{Bevarelse af livscyklus} \begin{lstlisting}[style=p5style,caption={Minimal p5.js-skitse.}] function setup() { createCanvas(400, 400); } function draw() { background(220); ellipse(mouseX, mouseY, 50, 50); } \end{lstlisting} \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. \subsection{Oprettelse af lærred} Den 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{}-element inden for DOM'en. Skitsen må forhandle med den eksisterende side snarere end at eje hele skærmen. \subsection{Instance mode} p5.js introducerer en vigtig flugtvej fra det globale navnerum: \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 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. \subsection{Hvad der ændrede sig, hvad der ikke gjorde} p5.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. % ============ 4. AC PIECE-API'EN ============ \section{AC Piece-API'en (2021--)} \label{sec:ac} \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. \subsection{Fem livscyklusfunktioner} \begin{lstlisting}[style=acjsstyle,caption={Minimalt AC piece.}] function boot({ screen, params }) { // Kører én gang ved indlæsning } 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")) { // Håndtér mellemrumstast } } function sim() { // Opdatér tilstand ved 120fps } export { boot, paint, act, sim }; \end{lstlisting} De fem funktioner er: \begin{itemize} \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. \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). \item \texttt{act(\$api)} --- kaldes én gang per inputhændelse. Konsoliderer Processings hændelses-callbacks (\texttt{mousePressed()}, \texttt{keyPressed()}) til ét samlet indgangspunkt. \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}. \item \texttt{leave(\$api)} --- oprydning ved afslutning. Ingen ækvivalent i Processing, hvor skitser simpelthen terminerer. \end{itemize} Hver funktion er valgfri. Et piece, der kun eksporterer \texttt{paint}, er et gyldigt, fungerende program. \subsection{API-injektion via destrukturering} Den 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: \begin{lstlisting}[style=acjsstyle,caption={API-destrukturering i 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} Dette design har flere konsekvenser: \begin{enumerate} \item \textbf{Ingen global forurening.} Modulniveau-variabler er piece-tilstand; API-funktioner er parametre. Der er intet omgivende navnerum at kollidere med. \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. \item \textbf{Komponerbarhed.} Flere pieces kan sameksistere i den samme JavaScript-kontekst uden API-kollisioner, hvilket muliggør platformens piece-skiftning og indlejringsmekanismer. \item \textbf{Opdagelighed.} Autokomplettering i editorer virker på det destrukturerede parameterobjekt og giver en naturlig måde at udforske API'en. \end{enumerate} Dette 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. \subsection{Adskillelse af simulation og rendering} \label{sec:simsep} Processings \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.'' AC adskiller disse eksplicit: \begin{itemize} \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. \item \texttt{paint()} kører med skærmens opdateringshastighed (begrænset til ca. 165fps) og er kun ansvarlig for at rendere den aktuelle tilstand. \item \texttt{act()} kører én gang per inputhændelse, umiddelbart når hændelsen ankommer. \end{itemize} Denne 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. \subsection{Samlet hændelseshåndtering} Processing distribuerer inputhåndtering på tværs af globale variabler og valgfrie callbacks: \begin{lstlisting}[style=processingstyle] // Processing: spredt inputmodel void draw() { if (mousePressed) { /* poll tilstand */ } } void mousePressed() { /* callback */ } void keyPressed() { /* callback */ } void mouseDragged() { /* callback */ } \end{lstlisting} AC konsoliderer al input i \texttt{act()} med et strengbaseret hændelsesmatchningsystem: \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} Mø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. \subsection{Tegneprimitiver: tilstandsløse som standard} Processing 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: \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); // Ingen tilstandslæk mellem kald } \end{lstlisting} \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. \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. \subsection{Ingen lærredskonfiguration} I 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. Dette 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. % ============ 5. API-OVERFLADE SAMMENLIGNING ============ \section{API-overfladesammenligning} \label{sec:comparison} Tabel~\ref{tab:lifecycle} sammenligner livscyklusmodellerne. Tabel~\ref{tab:drawing} sammenligner tegneprimitiver. \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(\$)} \\ Logik & (i draw) & (i draw) & \texttt{sim(\$)} \\ Input & callbacks & callbacks & \texttt{act(\$)} \\ Oprydning & --- & \texttt{remove()} & \texttt{leave(\$)} \\ \midrule Renderrate & 60fps & 60fps & skærm Hz \\ Logikrate & 60fps & 60fps & 120fps fast \\ Scope & globalt & globalt/inst. & injiceret \\ \bottomrule \end{tabularx} \caption{Livscyklussammenligning. \texttt{\$} betegner destruktureret API-injektion.} \label{tab:lifecycle} \end{table} \begin{table}[h] \small \centering \begin{tabularx}{\columnwidth}{lXX} \toprule \textbf{Processing/p5} & \textbf{AC} & \textbf{Noter} \\ \midrule \texttt{background()} & \texttt{wipe()} & Verbum, ikke egenskab \\ \texttt{fill() + stroke()} & \texttt{ink()} & Samlet, kædebar \\ \texttt{ellipse()} & \texttt{circle()} & Opkaldt efter form \\ \texttt{rect()} & \texttt{box()} & Kortere navn \\ \texttt{line()} & \texttt{line()} & Uændret \\ \texttt{point()} & \texttt{plot()} & Graf-metafor \\ \texttt{text()} & \texttt{write()} & Aktivt verbum \\ --- & \texttt{flood()} & Fyld region \\ --- & \texttt{paste()} & Buffer-kompositing \\ --- & \texttt{form()} & 3D-rendering \\ \bottomrule \end{tabularx} \caption{Sammenligning af tegneprimitiver.} \label{tab:drawing} \end{table} \subsection{Navngivningsfilosofi} Processings 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. Dette 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.'' \subsection{Farvemodel} Processing 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. AC 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: \begin{itemize} \item RGB-værdier: \texttt{ink(255, 100, 50)} \item Navngivne farver: \texttt{ink("pink")}, \texttt{ink("navy")} \item Gråtone: \texttt{ink(128)} \item Alfa: \texttt{ink(255, 0, 0, 128)} \end{itemize} Navngivne 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. % ============ 6. TILSTANDSSTYRING ============ \section{Tilstandsstyring} \label{sec:state} \subsection{Processing: globale variabler} \begin{lstlisting}[style=processingstyle] int x = 100; int y = 100; void draw() { background(0); x += 1; ellipse(x, y, 20, 20); } \end{lstlisting} Tilstand 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. \subsection{AC: modulniveau-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 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. Adskillelsen 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. % ============ 7. SLÆGTSKABET ============ \section{Slægtskabet} \label{sec:genealogy} \subsection{Design By Numbers (1999)} Maedas 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. AC arver DBN's minimalisme i navngivning (korte, aktive verber) og dets overbevisning om, at API'en bør være udtømmende lærbar. \subsection{Processing (2001)} Processing~\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. AC arver livscyklusfunktionsmodellen, men opdeler \texttt{draw()} i tre hensyn (\texttt{paint}, \texttt{sim}, \texttt{act}). \subsection{p5.js (2014)} p5.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. AC 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{