I think that makes it the second (production-ready) language to have a primarily-structural type system, after TypeScript/Flow(/and Closure to some extent) for JS. I wonder if it will follow in their impressive footsteps or if it will tread new territory.
One of the things that Flow gets right that TypeScript doesn't yet support is switching to nominal type-checking between class instances. In TypeScript you can assign an instance of one class to an instance of another as long as they have compatible fields. Compare:
TypeScript doesn't have any understanding of prototypes or prototypal inheritance, which is a big gap considering that it's a fundamental aspect of JS.
I'm really hoping Luau will come to do the right thing with tables and prototypes. Perhaps it already does, but unfortunately there doesn't seem to be a Luau playground to try in the browser.
Luau already has some notion of nominal types to deal with the fact that the Roblox API is basically a ton of C++ classes that have been mapped over via the FFI. Some of these types are totally structurally identical and yet incompatible.
We'd like to afford the same kind of ideas for native Luau code, but we're not there yet.
Super happy to see this released, and also for all the kids getting started programming on Roblox learning that there is a better way than random tag-checked mush :-)
Good on you all!
A regular MOVE is sort-of structural. It moves field i of the source to field i of the destination. Source and destination need not be of the same type, though.
MOVE CORRESPONDING is nominal. It moves field Foo of the source to field Foo of the destination (leaving fields that do not have corresponding items alone)
In both cases, data may be converted, for example from alphabetic to alphanumeric.
Funny that you would mention that in a thread on a statically-typed language based on Lua. Don't you need some insane mechanism to be flexible at runtime anyways? Either it will be reflection, or something like prototypes (in OO languages).
I think OCaml isn't just structural. For example, sum types (variants in OCaml) have a nominal form which is the default: https://ocaml.org/manual/coreexamples.html#s%3Atut-recvarian..., but also a structural form, polymorphic variants: https://ocaml.org/manual/polyvariant.html. I think it's the same for records, I didn't find a way to express the type "a record that has a certain field" as an argument of a function. You can do this with objects and modules I think, but not with records.
I forgot about OCaml (since I normally associate it with the more sophisticated typing stuff). I don't know if I'd completely count Go since interfaces only apply to methods, not fields
I was thinking of how you can embed types in structs. You automatically dereference the fields and methods of the components directly from the outside.
Yep, in go the inheritance (using the term loosely) structure can apply to interfaces (which specify groups of functions) and structs (which specify groups of data) and roughly does the same thing in both instances.
> In TypeScript you can assign an instance of one class to an instance of another as long as they have compatible fields.
Fun fact: If you add a private field to a class it'll behave nominally in TS. This is because private fields kinda require nominal relations to function. So, in a way, it does support "switching" to nominal type checking for classes - the opt in is simply per-class.
But variance depends on position where the value is used, not at the time of declaration, superclass/subclass at parameter/return value position can't be correctly encoded like this, can it?
I think most languages define variance at type definition level, notable exceptions being Kotlin which supports both [0][1] and Flow. But yeah, TS doesn't support (variable-)declaration-site variance which I didn't realize you were asking in my previous answer.
I'm less familiar with OCaml and don't know off the top of my head. Doing a quick search I was only able to find references to type declaration variance [0], though I learned that Java also supports use-site variance too [1]
> Luau’s type system is structural by default
I think that makes it the second (production-ready) language to have a primarily-structural type system, after TypeScript/Flow(/and Closure to some extent) for JS. I wonder if it will follow in their impressive footsteps or if it will tread new territory.
One of the things that Flow gets right that TypeScript doesn't yet support is switching to nominal type-checking between class instances. In TypeScript you can assign an instance of one class to an instance of another as long as they have compatible fields. Compare:
Flow: https://bit.ly/3jZx4rB
TS: https://tsplay.dev/mZaL1N
TypeScript doesn't have any understanding of prototypes or prototypal inheritance, which is a big gap considering that it's a fundamental aspect of JS.
I'm really hoping Luau will come to do the right thing with tables and prototypes. Perhaps it already does, but unfortunately there doesn't seem to be a Luau playground to try in the browser.