what parts of the language might be novel
It's hard to know for sure what is novel, because it seems that a number of our "original inventions" were also invented elsewhere, perhaps before or after, but it's safe to say that I'm not an expert about what everyone else has previously done :)
- The "turtles" type system (unified object type system, with turtles the whole way down; no intrinsics).
- Reference as an object: Variables are objects, and properties are objects (and properties each define their own class) -- not sure if this is new, but I've never used a language take this approach.
- Funky interfaces - https://xtclang.blogspot.com/2019/07/a-pane-in-glass.html
- The approach to equality (based on funky interfaces) - https://xtclang.blogspot.com/2019/06/the-quest-for-equality.html
- The solution to "null" - https://xtclang.blogspot.com/2019/07/null-is-no-exception.html (although it looks like Gavin took the same approach already in Ceylon)
- "conditional" methods, which are basically a language-recognized formalization of the option type - https://xtclang.blogspot.com/2019/06/conditional-methods.html
- conditional mixins - e.g. https://xtclang.blogspot.com/2019/07/composition.html
- Auto-narrowing types (combined with co-variance) - there's no doc on this one yet. As a feature, it's incredibly obvious and long overdue, but it's hard technically to implement without being designed into the type system. Basically, when a class C refers to "C", it doesn't mean "C", it means "this type", which automatically narrows as the type is used in other compositions.
- Virtual children (which are also auto-narrowing types) ... no doc yet on this one either, but assume something like:
class BaseParent
{
mixin MixinChild {...}
class AbstractChild {...}
@MixinChild class ConcreteChild extends AbstractChild {...}
}
class DerivedParent extends BaseParent
{
@Override mixin MixinChild {...}
@Override class AbstractChild {...}
@Override class ConcreteChild {...}
}
The call chain for any method on an instance of BaseParent.ConcreteChild is not surprising: BaseParent.MixinChild, BaseParent.ConcreteChild, BaseParent.AbstractChild, Object. What is eye opening is the call chain for any method on an instance of DerivedParent.ConcreteChild: DerivedParent.MixinChild, BaseParent.MixinChild, DerivedParent.ConcreteChild, BaseParent.ConcreteChild, DerivedParent.AbstractChild, BaseParent.AbstractChild, Object.
The ability to "sandwich" behavior is incredibly powerful. The above example is weak, because there's only one ConcreteChild, but what if there were a hundred, like you find in https://github.com/xtclang/xvm/tree/master/src/org/xvm/asm/op or https://github.com/xtclang/xvm/tree/master/src/org/xvm/compiler/ast ? Being able to virtually augment base class functionality in a controlled, non-diamond-creating manner is going to be incredible, but we haven't yet bootstrapped those two toolchains (Compiler and Assembler as represented by the above links to AST and ops) into Ecstasy to understand the full ramifications of such an approach; so far, the most complex use cases have only been white-board simulations and thought experiments. Nonetheless, the combination of a component (the encapsulation of the domain of those children) combined with the ability to compose without inheritance (e.g. aggregation by delegation, e.g. mixins as cross-cutting compositions), and you can much better manage complexity than in a purely inheritance-based hierarchy with an inflexible super-structure.
most impactful vs. existing languages
It's also really hard for me to answer this, because I'm so close to the language. But here goes ...
- Annotations are mixins. This one is terribly useful; see for example https://github.com/xtclang/xvm/blob/master/xsrc/system/annotations/LazyVar.x and https://github.com/xtclang/xvm/blob/master/xsrc/system/annotations/FutureVar.x.
- Proper immutability, with clean "const" construction (i.e. no "this" becomes visible until after the object is immutable).
- Service-based concurrency model, with no shared mutable state (i.e. all memory management is thread local, except for immutable state, auto-proxies, and messages passed). In some ways, I imagine this as being the best of Smalltalk message-passing and the Erlang process model, combined. (I'm not exactly an objective judge, though.)
- Multi-returns - not unique, but this is far too unusual in the PL world for such an obviously useful feature.
- Tuples - again, this is far too unusual in the PL world for such an obviously useful feature.
- Invocation in Ecstasy is very powerful. Both methods and functions are real, first-class citizens. Method invocation support pass-by-tuple, or pass-by either -in-order or -name or combination thereof. Support for default argument values. All of which work with narrowing types using call chain capping (no doc on this yet). Everything above supports currying, both partial and full.
- Proper decimal support (not yet implemented, but the design is for IEEE-754 32, 64, 128, and var-len decimal). This is important because the only thing in the entire universe that uses binary floating point is the man-made computer.
- That said, we will support binary floats (16, 32, 64, 128, and var-len) for hardware-accelerated work (like ML), and n-dimensioned arrays (with 1d & 2d accelerated). For ML, we plan to support compact floats including bfloat16 (not implemented yet), and possibly 8-bit if one gets even semi-standardized like bloat16 is.
- Type parameters aren't just not-erased; they're actually types; this applies to both class-level and method/function-level type parameters. This doesn't seem so big until you go back to using a language without reified types, and by "reified", I don't just mean that the type isn't erased, but rather that the type parameter becomes a type that you can use just like you use the word "String" or "Int".
- All resources are provided by injection; without injection, the language cannot even do I/O. The language has no concept of "that which lies beneath", so access to any system resource has to be injected into an application.
- Using injection, the language is designed for an "unknowable" managed runtime environment (could be the cloud, could be a device), i.e. every bit used, every CPU cycle consumed, every I/O can be tracked (or metered or mocked or intercepted). This is obviously one of the driving factors in the design, and one of the reasons why we could not find a suitable substrate on which to build this. (Originally, I wanted to use V8 or the JVM.)
I suppose the long and the short of this answer is that the syntax is rather minor; we designed the syntax to make it easy for C++ and C# and Java developers to read Ecstasy, and to be able to start writing it almost immediately. The real value is in the type system and the design for the managed run-time, and it will take effort over time to make the value of that design visible.
As an aside, the following example was one of the "aha" moments for me. This index code is basically how I would have written it (i.e. designed the data structure) in C, except here it's completely type-safe and OO -- but without having to build a class for every little detail:
https://github.com/xtclang/xvm/blob/master/xsrc/system/collections/ListMap.x
https://github.com/xtclang/xvm/blob/master/xsrc/system/collections/ListMapIndex.x
There's a lot to unpack in that code, but it's glimpse at what is possible. And that code compiles. And it runs. And it works.
Sorry for the long response ... but it's hard for me to not be excited.