diff --git a/sx/content/pages.py b/sx/content/pages.py index 2e735ab..a4ea85b 100644 --- a/sx/content/pages.py +++ b/sx/content/pages.py @@ -72,7 +72,7 @@ ESSAYS_NAV = [ ("On-Demand CSS", "/essays/on-demand-css"), ("Client Reactivity", "/essays/client-reactivity"), ("SX Native", "/essays/sx-native"), - ("The SX Manifesto", "/essays/sx-manifesto"), + ("The SX Manifesto", "/philosophy/sx-manifesto"), ("Tail-Call Optimization", "/essays/tail-call-optimization"), ("Continuations", "/essays/continuations"), ] diff --git a/sx/sx/essays.sx b/sx/sx/essays.sx index 3b96229..2c36ba8 100644 --- a/sx/sx/essays.sx +++ b/sx/sx/essays.sx @@ -1,5 +1,336 @@ ;; Essay content — static content extracted from essays.py +;; --------------------------------------------------------------------------- +;; Philosophy section content +;; --------------------------------------------------------------------------- + +(defcomp ~philosophy-index-content () + (~doc-page :title "Philosophy" + (div :class "space-y-4" + (p :class "text-lg text-stone-600 mb-4" + "The deeper ideas behind SX — manifestos, self-reference, and the philosophical traditions that shaped the language.") + (div :class "space-y-3" + (map (fn (item) + (a :href (get item "href") + :sx-get (get item "href") :sx-target "#main-panel" :sx-select "#main-panel" + :sx-swap "outerHTML" :sx-push-url "true" + :class "block rounded border border-stone-200 p-4 hover:border-violet-300 hover:bg-violet-50 transition-colors" + (div :class "font-semibold text-stone-800" (get item "label")) + (when (get item "summary") + (p :class "text-sm text-stone-500 mt-1" (get item "summary"))))) + philosophy-nav-items))))) + +(defcomp ~essay-sx-and-wittgenstein () + (~doc-page :title "SX and Wittgenstein" + (p :class "text-stone-500 text-sm italic mb-8" + "The limits of my language are the limits of my world.") + (~doc-section :title "I. Language games" :id "language-games" + (p :class "text-stone-600" + "In 1953, Ludwig " (a :href "https://en.wikipedia.org/wiki/Ludwig_Wittgenstein" :class "text-violet-600 hover:underline" "Wittgenstein") " published " (a :href "https://en.wikipedia.org/wiki/Philosophical_Investigations" :class "text-violet-600 hover:underline" "Philosophical Investigations") " — a book that dismantled the theory of language he had built in his own earlier work. The " (a :href "https://en.wikipedia.org/wiki/Tractatus_Logico-Philosophicus" :class "text-violet-600 hover:underline" "Tractatus") " had argued that language pictures the world: propositions mirror facts, and the structure of a sentence corresponds to the structure of reality. The Investigations abandoned this. Language does not picture anything. Language is " (em "used") ".") + (p :class "text-stone-600" + "Wittgenstein replaced the picture theory with " (a :href "https://en.wikipedia.org/wiki/Language_game_(philosophy)" :class "text-violet-600 hover:underline" "language games") " — activities in which words get their meaning from how they are employed, not from what they refer to. \"Slab!\" on a building site means \"bring me a slab.\" The same word in a dictionary means nothing until it enters a game. Meaning is use.") + (p :class "text-stone-600" + "Web development is a proliferation of language games. HTML is one game — a markup game where tags denote structure. CSS is another — a declaration game where selectors denote style. JavaScript is a third — an imperative game where statements denote behaviour. JSX is a fourth game layered on top of the third, pretending to be the first. TypeScript is a fifth game that annotates the third. Each has its own grammar, its own rules, its own way of meaning.") + (p :class "text-stone-600" + "SX collapses these into a single game. " (code "(div :class \"p-4\" (h2 title))") " is simultaneously structure (a div containing an h2), style (the class attribute), and behaviour (the symbol " (code "title") " is evaluated). There is one syntax, one set of rules, one way of meaning. Not because the distinctions between structure, style, and behaviour have been erased — they haven't — but because they are all expressed in the same language game.")) + (~doc-section :title "II. The limits of my language" :id "limits" + (p :class "text-stone-600" + "\"" (a :href "https://en.wikipedia.org/wiki/Tractatus_Logico-Philosophicus" :class "text-violet-600 hover:underline" "Die Grenzen meiner Sprache bedeuten die Grenzen meiner Welt") "\" — the limits of my language mean the limits of my world. This is proposition 5.6 of the Tractatus, and it is the most important sentence Wittgenstein ever wrote.") + (p :class "text-stone-600" + "If your language is HTML, your world is documents. You can link documents. You can nest elements inside documents. You cannot compose documents from smaller documents without a server-side include, an iframe, or JavaScript. The language does not have composition, so your world does not have composition.") + (p :class "text-stone-600" + "If your language is React, your world is components that re-render. You can compose components. You can pass props. You cannot inspect a component's structure at runtime without React DevTools. You cannot serialize a component tree to a format another framework can consume. You cannot send a component over HTTP and have it work on the other side without the same React runtime. The language has composition but not portability, so your world has composition but not portability.") + (p :class "text-stone-600" + "If your language is s-expressions, your world is " (em "expressions") ". An expression can represent a DOM node, a function call, a style declaration, a macro transformation, a component definition, a wire-format payload, or a specification of the evaluator itself. The language has no built-in limits on what can be expressed, because the syntax — the list — can represent anything. The limits of the language are only the limits of what you choose to evaluate.") + (~doc-code :lang "lisp" :code + ";; The same syntax expresses everything:\n(div :class \"card\" (h2 \"Title\")) ;; structure\n(css :flex :gap-4 :p-2) ;; style\n(defcomp ~card (&key title) (div title)) ;; abstraction\n(defmacro ~log (x) `(console.log ,x)) ;; metaprogramming\n(quote (div :class \"card\" (h2 \"Title\"))) ;; data about structure") + (p :class "text-stone-600" + "Wittgenstein's proposition cuts both ways. A language that limits you to documents limits your world to documents. A language that can express anything — because its syntax is the minimal recursive structure — limits your world to " (em "everything") ".")) + (~doc-section :title "III. Whereof one cannot speak" :id "silence" + (p :class "text-stone-600" + "The Tractatus ends: \"" (a :href "https://en.wikipedia.org/wiki/Tractatus_Logico-Philosophicus#Proposition_7" :class "text-violet-600 hover:underline" "Whereof one cannot speak, thereof one must be silent") ".\" Proposition 7. The things that cannot be said in a language simply do not exist within that language's world.") + (p :class "text-stone-600" + "HTML cannot speak of composition. It is silent on components. You cannot define " (code "~card") " in HTML. You can define " (code "