Singular Concept of Type
Recently I posted a tweet which caused some interesting debate:

I wanted to clarify my thinking in a way that 140 characters often does not permit one to do.
Preamble
First, cleanse your mind of everything you know about how classes and structs are implemented in any programming language ever. This discussion is not biased by previous practical solutions, it is theory based.
Second, I cannot promise it offers anything revelatory. I only know what I know, and am probably not alone in noting the below.
Background
Currently we have this underlying concept of type, and then these specialised derivations of type known as classes or structs or some other names (depending on language).
But teaching what a class is vs. a type to those new to programming leads to confusion.
Further, the fact that several people expressed conflicting views on that tweet thread alone shows we as an industry suffer from this ambiguity.
And even deciding whether to use a class or struct for an experienced programmer might not be obvious for a given scenario in a given language, and so becomes an arbitrary choice at that moment in time that silently may or may not hold as the code around it evolves.
So why this abstraction when the concept of type alone is expressive enough to say "this type X can do Y", as well as "this variable is of type X", which is semantically the same as "x instanceof X".
Alternate Type System
The goal would be to replace all that nomenclature with just a single universal concept of type.
Some argue that a class is explicitly the binding of data with functions, but a type definition in this alternate system would be equally capable of having member methods if it made sense for that type. That's an implementation detail after all.
And given the aforementioned viewpoint that a class is a derivative of type, and a class can have methods, a class is thus just a type with methods. Hence, supporting this mechanism causes no contradiction to the goal of the alternate system.
And it might be that some choose a struct over a class to influence where that memory is allocated, but that would be relying on an opaque implementation detail that you have no actual assurances over - thereby invalidating the argument.
So why not just annotate a standard type definition detailing it's semantics? Quoting Eric Lippert:
Surely the most relevant fact about value types is not the implementation detail of how they are allocated, but rather the by-design semantic meaning of “value type”, namely that they are always copied “by value”
But if and only if the compiler or runtime actually respects these annotations, and not have it be a guessing game for the programmer:
The insertion (called inline expansion or inlining) occurs only if the compiler's cost/benefit analysis show it to be profitable
This only perpetuates the illusion that the compiler knows best, or is smarter than the programmer - a gripe seemingly shared by Jonathan Blow in his recent compiler stream.
Another reason for this concept of structs as a type specialization might be to represent data that is marshalled between languages. But whilst JavaScript has many, many flaws...., it's object literal type is inherently serializable to JSON, and seeing as nigh on all major languages support JSON (de)serialization why not follow that lead?
We would even support custom serialization of properties if contrary to the default, an intent that is just an annotation away:
type Foo {
int bar
Foo() : Foo => {...}
@customFunctionSerializer
sq(x : float) : float => x * x
}
Moreover, maybe the language would allow one to define their own hyper-annotations that encompasse a set of annotations.
Especially if many types in your system exhibit the same semantics and you tire of decorating each one in turn with the same attribute list:
@hyperAnnotation = @someAnnotation, @anotherAnnotation
@hyperAnnotation
type Baz
{
...
}
@hyperAnnotation
type Xyz
{
...
}
OOP fans can relax also, there is nothing prohibiting a type definition in this system from being a composition of other types, or inheriting from a supertype.
Having a single universal concept of type does not limit the expressivity in any way.
Summary
That was a short ramble, but the point is that the addition of classes and structs (and any other derivative of a type) seems to convolute programming needlessly when a simple universal concept of type is:
- equally as expressive syntactically
- sharply focused on expressing the actual semantic intent of types in the system
- not semantically opaque (ie. the compiler would do exactly what the programmer intends)
- simpler to teach as a concept to new programmers
- simpler to agree on as a concept for programmers in general
Feedback welcome on what I may have missed, unless you're about this life.
ps. I'm told Go does not have classes etc. either, but having no experience with it I cannot comment on whether their motivations intersect with my reasoning above.
D. Ho (@ComethTheNerd)