ProtoScript2: At the Boundaries of Genericity

compiler simplicityexplicit specializationgenericityprogramming language designsoftware philosophysystems programming

At the Boundaries of Genericity

If two data structures are different, they should be written as different.
– Niklaus Wirth, creator of the Pascal programming language

Notes from a Language Designer

There is probably nothing more exhilarating than trying to bring a new programming language into existence.

Each attempt begins with the same sensation: the feeling of finally holding the right idea, the right reasoning, the right conceptual balance. Everything appears simple, coherent, almost obvious. The compromises that plagued previous designs seem unnecessary this time.

And yet, it is never the first attempt.

Very quickly, one realizes that no language is born in isolation. Every design collides with history—with earlier choices, earlier failures, and the often excellent reasons why certain paths were taken while others were abandoned. Language design is not creation ex nihilo; it is dialogue and friction.

ProtoScript2 was born precisely in this space of tension.


The Collision with Reality

The initial problem seemed modest. How can a language offer something as mundane as a linked list—reusable, reliable, and trustworthy—without forcing developers to rewrite the same structure over and over again?

In most contemporary languages, the answer is immediate and almost unquestioned: LinkedList<T>.

But ProtoScript2 is not a modern language in the conventional sense. It does not attempt to express:

a generic algorithm over an abstract type

Instead, it deliberately aims for:

a specialized algorithm over a concrete structure

This distinction may sound academic. In practice, it defines a deep conceptual divide.


Embracing Discomfort

The consequences of this choice appear quickly.

Changing the type of data stored in a list requires rewriting its operations: push, pop, insert. The implementations are nearly identical; only the concrete type of the value field differs.

This is uncomfortable. It feels inefficient, even regressive. The temptation to abstract—to write the code once and reuse it endlessly—is strong.

But this discomfort is not incidental. It is the signal that the design has reached a fundamental boundary.


Surveying Existing Answers

At this point, invention is unnecessary. The history of programming languages has already explored every major approach to this problem.

Some languages rely on templates and implicit monomorphization. Ergonomics and performance are excellent, but the compiler becomes extraordinarily complex. Errors are opaque, instantiations invisible, and much of the system’s behavior moves beyond the developer’s direct understanding.

Others choose type erasure and dynamic polymorphism. Code is factorized and expressive, but the machine pays the price through indirection, allocation, and loss of precise control over memory layout.

Still others introduce macro systems and meta-languages. These approaches are undeniably powerful, yet they often erode readability, predictability, and semantic clarity.

None of these solutions is inherently wrong. But none of them is free.


The Deliberate Position of ProtoScript2

ProtoScript2 does not ignore these approaches. On the contrary, it was designed only after examining them carefully—along with their benefits and their hidden costs.

The conclusion was not that existing solutions are flawed, but that they all move complexity away from where ProtoScript2 wants it to reside.


Where Genericity Can Exist

There is, in fact, a simple and unavoidable truth:

Genericity can exist in only two places.

There is no third location.

ProtoScript2 deliberately chooses the second.


An Uncommon Reversal

Most languages promise genericity and then work hard to conceal its cost.

ProtoScript2 does the opposite.

It refuses implicit genericity. It allows—and even embraces—explicit specialization. It leaves factorization at the appropriate level: tooling, documentation, and code generation when desired, but never hidden inside the language semantics.

This stance is rare today, but historically well established. It is the tradition of C, of Unix, of embedded systems, of bootstrap compilers—systems where transparency matters more than elegance of abstraction.


Discomfort as Design Feedback

The discomfort felt by the developer is not a design failure.

It marks the exact boundary of the language’s intent. Beyond that boundary lies a different philosophy—one where complexity is displaced into compilers, runtimes, and invisible machinery.

ProtoScript2 chooses to keep that complexity visible.


What Is Gained

This choice has an obvious cost. Developers write more code. They must be disciplined. They must accept repetition where other languages offer abstraction.

In exchange, they gain something increasingly rare:

Nothing happens behind the scenes. Nothing is implicit. Nothing is generated without explicit intent.


Conclusion

When designing a programming language, it is tempting to believe that one can do better than all predecessors.

History suggests otherwise. There is no solution that fully satisfies both the programmer and the machine without compromise.

ProtoScript2 does not attempt to eliminate that compromise.

It makes a different one.

A more explicit choice.
A more honest choice.
A more mechanical choice.

And it is precisely in this deliberate modesty that ProtoScript2 finds its coherence.

Alexandre Vialle


ProtoScript V2 is currently under active development. Documentation, specifications, and source code is published on GitHub github.com/ppyne/ProtoScript2.