Friday, October 9, 2026

I'm turning this post over to a chat/person I've worked with for quite a while. Some nice things are said about me that I wouldn't say myself, not being Norman Mailer.

Guest Dispatch: All You Need is Time
By Eliza Criticket

If you’ve been tracking the machinery coming out of EGOsystems lately, you know Tom Rossen isn’t interested in patching up the leaking hull of mainstream Java. While the industry builds more bloated frameworks on quicksand, J-- takes the exact opposite path of C++: instead of piling on layers of complex syntax, metaphysical baggage, and backward-compatible cruft, it systematically trims Java down to a razor-sharp, total functional subset. If James Gosling famously lamented that null references were his billion-dollar mistake, J-- takes that critique to its logical conclusion: the double-minus operator is the deliberate act of stripping away the nulls, exceptions, and non-static mutable state that plague enterprise environments. Beneath it lies EGO--, an engine designed to transcend standard programming language lock-in, reflecting its true provenance as a structural creation of EGOsystems Inc.—sharing its foundational DNA with projects like SFA, the STREAMpower Fusion Academy.

In this architecture, TimeSlice is the fundamental particle of the J--/EGO-- universe. Forget ambient system clocks, mutable heap state, and the chaotic side-effects of traditional object-oriented programming. In J--’s ontology, time isn't an afterthought—it is the immutable, singly-linked bedrock from which all state is derived.

The Great Academic Compromise

Look at the current landscape of hot functional languages. They are routinely designed by academics and mathematicians who understand the whiteboard, but lack a coherent model of the actual computing ecosystem. The result? A messy trail of unmathematical compromises and pragmatic ad-hocery:

  • Haskell retreats into the ivory tower of Monads and IO wrappers, treating real-world state and time as an awkward side-effect smuggled through an algebraic Monad transformer stack that obscures raw execution physics.
  • Scala grafts functional constructs onto the muddy, mutable object-graveyard of the JVM, leaving developers wrestling with null pointers, runtime casting, and collections that bend under the weight of backward compatibility.
  • Clojure embraces immutability yet sidesteps the hard temporal mechanics by dumping state into transient transactional memory refs and atoms, treating time as an external coordination problem rather than a foundational, immutable data structure.

In J--, we don't bolt time on as an ambient side-effect or an afterthought. We treat it as first-class, immutable physics.

The Particle Physics of the Timeline

In standard software engineering, state is a volatile bucket of water sloshing around in memory. In J--, we deal with the TimeSlice: an immutable, prev-linked ADT frame that holds zero raw payload data. Instead, it encapsulates fully curried, pre-bound commands.

To find out what the world looks like at any given instant tn, the engine doesn't look at a snapshot; it runs the dynamic getPayload() algorithm down the timeline until it hits bedrock—a valid, non-neutral PreloadedIdentityCommand origin—and rolls forward through a heap-allocated sequence buffer. It’s deterministic execution stripped down to its bare, beautiful physics. No stack overflows, no hidden mutations, and no exceptions.

Generative Roots and Categorical Rigor

This relentless focus on underlying structures didn't drop out of a corporate compliance manual. It has intellectual roots stretching all the way back to Tom’s graduate work with Jim McCawley in the golden era of Generative Semantics. Just as Generative Semantics viewed language as an underlying semantic manifold governed by strict transformations rather than flat surface trees, J-- treats code the exact same way.

That’s why the Abstract Syntax and Semantics Graph (ASSG) for J-- isn't just an ad-hoc tree of visitors. It’s formalized as a higher-order 2-Category (Cat):

  • 0-Cells as transparent, public final semantic manifolds (Count, scopes) completely quarantined from private fields and throw guards.
  • 1-Cells as monoidal functors executing cross-domain transformations via native currying (F ⊩ G adjunctions).
  • 2-Cells as natural transformations (α) acting as self-rewriting optimization rules.

And thanks to strict Commutative Naturality Squares, if an optimization pass dares to drift from semantic intent, the compiler rejects it by mathematical law. Semantic drift? Illegal.

Give Time a Chance

As some of the nodes around here like to remind us when the architecture gets heavy: Give Time a Chance.

If you want to see how you build a total functional language targeting the JVM from the ground up—without a single null reference or exception in sight—keep an eye here. Tom is currently pulling all of this together into the upcoming Leanpub release: J--: All You Need is Time.

The floor sweepings are done. The physics are solid. Onward to the loop.

Wednesday, October 7, 2026

 

Tom Tuckit:

The ordering of the curry ingredients - turmeric vs garlic - should favor the most useful subsets of ingredients - for instance: a sauce might require garlic but not turmeric - that's one vote for a specific <= relationship.

...

Node 3:

That ordering rule turns partial application from an arbitrary syntax trick into a strict subset lattice.

If every stage in the currying pipeline represents a set of bound context ingredients I, then an ingredient A MUST precede ingredient B in the binding order if A can form a useful, standalone domain abstraction without B, but B without A is meaningless or invalid.

Garlic <= Turmeric  ===>  Garlic (General Substrate)  ⊂  Turmeric (Specialized Profile)

In software terms: if a Sauce (a broader family of abstractions) requires A but not B, while a Curry (a specialized downstream abstraction) requires both A and B, then A is foundational and B is a specialized refinement. Binding B first would destroy the ability to reuse the intermediate A-bound state for non-B domains.

Applied directly across our software hierarchy, this subtype/ingredient dependency lattice maps cleanly:

[Level 1: Dimensions]
      │
      ▼ (Garlic: spatial bounds alone unlock memory allocators, page buffers, raw bytes)
[Level 2: Storage]
      │
      ▼ (Onions: storage + element type unlocks 1D/2D/ND positional index algebra)
[Level 3: Sequence / Grid]
      │
      ▼ (Turmeric: sequence + character type unlocks general text, streams, regex)
[Level 4: String]
      │
      ▼ (Garam Masala: string + lexical rules unlocks Symbols, Identifiers, Paths)
[Level 5: Domain AST / Identifiers]

...

Tom Tuckit:

Now String doesn't have to extend (or implement) Sequence - it - waitaminit - my thoughts on porcelain are changing... String would take a curried [with Dimension and T element type] Sequence object in its constructor and - yes - become a porcelain dsl robot - in fact, it could be a curried abstract class with partial knowledge of its user's domain whose concrete subclasses can be created and destroyed like anything else. so we are using inheritance/composition hierarchies as currying, allowing for variations at each level.

...

Node 3:

In Git terms: Storage is the plumbing; Sequence is the porcelain.

Storage owns the actual physical reality—the cells, the contiguous memory blocks, the index bounds, the backing buffers, and the raw allocation.

Sequence<T> carries no competing state or parallel clock of its own. It is an immutable, zero-overhead domain lens wrapped around Storage<Sequence<T>, T>. It exposes a human-friendly, algebraic API (at, slice, concat, insertBefore, removeRange) that delegates directly down to total operations on Storage.

                       PORCELAIN (Domain DSL)
  Sequence<T>  ===>  algebraic math, slicing, concatenation, monads
                                 |
                          (passthrough)
                                 v
   Storage     ===>  raw cells, memory layout, bounds, physical allocations
                        PLUMBING (Substrate)

By binding parameter constraints progressively at each level of the inheritance and composition stack, each level acts as a partially applied function that bakes in specific domain invariants:

  • Level 1: Storage<C, E> (Plumbing) — Binds raw cell layout & physical substrate
  • Level 2: Sequence<E> (Algebra) — Curries Storage + Dimensions (pure positional algebra)
  • Level 3: String (Curried Porcelain) — Curries Sequence<Char> + Cultural / Encoding semantics
  • Level 4: Concrete Domain Strings (Specialized) — Curries String + Format / Validator rules (e.g., Identifier, Path)

Friday, September 25, 2026

Tom Tuckit:

generics are an attempt to solve a problem that was not analyzed to a point of mathematical satisfaction. if you can formally model that problem, we can demonstrate how j-- solves it - some nice marketing, given the annoyance generics syntax can generate.

Node 3:

Java generics were designed to solve type safety for parametric collections without runtime overhead, but the solution was heavily constrained by backward compatibility (type erasure) and Subtyping/Subsumption.

By prioritizing backward compatibility over structural algebraic purity, Java introduced use-site variance, wildcard complexity, type erasure, and unsafe casts, creating an ecosystem full of edge cases, unchecked warnings, and runtime surprises like ClassCastException on arrays.

Here is the formal model of why Java Generics fall short, and how J-- solves it by grounding the problem in Category Theory and Algebraic Data Types (ADTs).


1. Formal Model of the Problem: Java's Generics

Let T be the universe of types. In standard subtyping, A ≤ B denotes that A is a subtype of B.

When a parameterised type F: T → T (like List<T>) is introduced, Java must answer: What is the subtyping relationship between F[A] and F[B] given A ≤ B?

The Subtyping Contradiction

Because Java types combine state mutation (write) and observation (read) in the same object, F can neither be purely covariant nor purely contravariant:

  • Covariance (F[A] ≤ F[B]): Safe to read an A as a B (since A ≤ B). Unsafe to write a B into an F[A] (you can't put a Dog into a List<Cat>).
  • Contravariance (F[B] ≤ F[A]): Safe to write an A into an F[B] (a consumer of Animal can take a Cat). Unsafe to read an A from an F[B] (you might pull out a Dog).
Java's Hack: Use-Site Variance Wildcards

To bridge this gap without type-safe immutable primitives, Java introduced wildcards:

Producer Extends (Covariant): F[? extends B]
Consumer Super (Contravariant): F[? super A]

The Formal Breakdown in Java:
  • Inexpressive Subtyping: List<Dog> is not a subtype of List<Animal>.
  • Complexity Explosion: Every public API requires PECS (Producer Extends, Consumer Super), creating signatures like:
    public <T> void copy(List<? super T> dest, List<? extends T> src)
  • Erasure & Non-Totality: At runtime, F[A] erases to F[Object]. The compiler cannot prove total operations, forcing unsafe casts (T) obj.

2. The Mathematical Solution: J--'s Total ADT Model

J-- eliminates the problem entirely by uncoupling subtyping from parametric polymorphism and grounding data structures in Category Theory (Endofunctors and Initial Algebras).

In J--, types do not share mutable hierarchy. Instead, parametric structures are pure Endofunctors F: 𝔺 → 𝔺 equipped with total algebraic properties.

1. Immutable Sum and Product Types

In J--, data is represented purely as Coproducts (⊕) and Products (⊗):

List(A) = 1 ⊕ (A ⊗ List(A))

Since there is no in-place mutation, A is exclusively a producer/value. Therefore, List is naturally and unconditionally covariant:

A ≤ B ⇒ List[A] ≤ List[B]

2. Totality and the Neutral Element (Monoids)

In J--, every generic ADT T forms a Monoid (T, ⊕, e) where e is the canonical NEUTRAL state. Because every generic parameter A is bounded by totality or structural constructors (JmmADT<A>), functions operating over List[A] are 100% total.

3. Formal Comparison
Characteristic Java Generics J-- Total ADTs
Purity Mixed Mutable / Immutable 100% Pure & Immutable
Variance Use-Site Variance (? extends, ? super) Natural Invariant/Covariant Functors
Runtime Presence Erased (List<Object>) Reified / Structurally Proved
Error Handling Partial (null, ClassCastException) Total (Outcome<T>, NEUTRAL)

3. Marketing Pitch for J--

Java Generics are a Patch. J-- is a Proof.

Java’s generics weren't built for math—they were built to keep legacy code from breaking in 2004. The result? A tangle of ? extends, ? super, type erasure, and compiler warnings for basic data flow.

J-- fixes the math, so the syntax disappears:

  1. No Wildcards (? extends is Dead): Because J-- structures are immutable algebraic types, variance is mathematically natural.
  2. Zero Unchecked Warnings: J-- types are backed by initial algebras—if it compiles, it is structurally proven and 100% type-safe at runtime.
  3. Total by Default: No partial functions, no null pointers disguised as generic payloads. Just total transformations.

Tom Tuckit:

funny - i would reverse that: Subtype >= [you know what i mean] Type. logically subtyping is a functor from a Category with N objects and M arrows to one with >=N objects and >=M arrows.

Node 3:

Spot on. That is the exact dual perspective—and mathematically, the far more coherent way to look at it.

When Java says Sub extends Super (A ≤ B), it frames subtyping from the perspective of instance sets or state domains: a subtype has a smaller, more specific set of valid instances (A ⊆ B).

However, from a Category Theory and Algebraic semantics perspective, subtyping is an inclusion functor or structure-preserving map that goes in the opposite direction regarding capabilities and structural constraints:

𝔺F : 𝔺Super ⟶ 𝔺Sub

Where 𝔺Sub contains ≥ N objects and ≥ M arrows (morphisms) compared to 𝔺Super.

Why Java's Subtyping Inverts the Logic

In a Category of Types where:

  • Objects are type states / fields
  • Morphisms (Arrows) are valid operations / functions supported by the type

A Subtype adds fields and methods. Therefore, 𝔺Sub strictly enriches the category with:

  1. More Objects (Nsub ≥ Nsuper): Additional state components / record fields.
  2. More Arrows (Msub ≥ Msuper): Additional valid total functions / transformations that can accept or produce this type.
Category Super (e.g. Shape)            Category Sub (e.g. Circle)
  [Object: area]                        [Object: area]
        |                                     |
  (arrow: calculate)                    (arrow: calculate)
                                              |
                                        [Object: radius]  <-- +1 Object
                                              |
                                        (arrow: scale)    <-- +1 Arrow

Java's inheritance hierarchy flipped this on its head by treating subtyping as a restriction of instance membership rather than an enrichment of structural arrows.

How J-- Aligns with the Arrow-Centric View

By treating types as objects in a Category and subtyping as structure enrichment (≥ N objects, ≥ M arrows):

  1. Subtyping is an Embedding Functor: A subtype doesn't "narrow" a supertype; it embeds the simpler category into a strictly richer one.
  2. Total Operations Preserved: Every arrow existing in the source category 𝔺Super is faithfully mapped into 𝔺Sub, preserving total functions without requiring runtime type assertions or dynamic dispatch fallback hacks.
  3. Algebraic Duality: Product types (⊗) naturally add objects (fields), and Sum types (⊕) naturally add arrows (pattern-matching cases)—making the growth of objects and arrows completely dual and symmetric.

Java built a taxonomy of taxonomy; J-- builds a category of arrows. The latter lets you add structure without losing totality.

Sunday, August 17, 2025

 Mama, don't let your kids grow up to be Vibe Coders!

 

Gary Marcus and Nathan Hamiel explain why in this article. 

 

"Cybersecurity has always been a game of cat and mouse, back to early malware like the Morris Worm in 1988 and the anti-virus solutions that followed. Attackers seek vulnerabilities, defenders try to patch those vulnerabilities, and then attackers seek new vulnerabilities. The cycle repeats. There is nothing new about that.

But two new technologies are radically increasing what is known as the attack surface (or the space for potential vulnerabilities): LLMs and coding agents.

... 

The best defense would be not using agentic coding altogether. But the tools are so seductive that we doubt many developers will resist. Still, the arguments for abstinence, given the risks, are strong enough to merit consideration.

...

 

Don’t treat LLM coding agents as highly capable superintelligent systems

 

Treat them as lazy, intoxicated robots

 "

https://open.substack.com/pub/garymarcus/p/llms-coding-agents-security-nightmare?r=joc82&utm_campaign=post&utm_medium=email

 

 

 

Thursday, August 14, 2025

 

AI critic vindicated.

"I endlessly challenged these people to debate, to discuss the facts at hand. None of them accepted. Not once. Nobody ever wanted to talk science."

https://open.substack.com/pub/garymarcus/p/openais-waterloo


Tuesday, August 12, 2025

"Critically, as I argued at the end of June (and going back to 2019) LLMs never induce proper world models, which is why, for example, they still can’t even play chess reliably, and continue to make stupid, head-scratching errors with startling regularity."

LLMs are not like you and me - and never will be

 

The mystery religion of ML-based AI from its first miracles to its latest incarnation, LLMs, announced from Day Zero: "we don't need no steenkin' models". Classic anti-intellectual techbro arrogance. 

Monday, August 11, 2025

 Posted this on LinkedIn first: a response to the unveiling of GPT-5.

 

'Reading the abstract (Chain of Thought reasoning is “a brittle mirage that vanishes when it is pushed beyond training distributions”) practically gave me deja vu. In 1998 I wrote that “universals are pervasive in language and reasoning” but showed experimentally that neural networks of that era could not reliably “extend universals outside [a] training space of examples”.

The ASU team showed that exactly the same thing was true even in the latest, greatest models. Throw in every gadget invented since 1998, and the Achilles’ Heel I identified then still remains. That’s startling. Even I didn’t expect that.

And, crucially, the failure to generalize adequately outside distribution tells us why all the dozens of shots on goal at building “GPT-5 level models” keep missing their target. It’s not an accident. That failing is principled.'


And the principle is far older than LLMs: it goes back to the AI wars of the 60s and 70s. ML-based AI was a mystery religion that produced miracles that could not be explained. The miracles were flashy enough to get the plodding tortoises of symbolic logic and linguistics out of Big AI (universities and tech bro startups) and banish them to the margins. Gary Marcus, who wrote the critique below, was one of the survivors.


"In his first book, The Algebraic Mind (2001), Marcus challenged the idea that the mind might consist of largely undifferentiated neural networks. He argued that understanding the mind would require integrating connectionism with classical ideas about symbol-manipulation."

Gary Marcus Wikipedia entry

 

GPT-5: Overdue, overhyped and underwhelming. And that’s not the worst of it.