-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements targeting serialization & data #4232
Comments
I have two main ones that I’m particularly interested in. This proposal from @munificent a few years ago: https://github.com/dart-lang/language/blob/main/working/tagged-strings/feature-specification.md And I would really like to see proper core language support for the RFC 8949 Concise Binary Object Representation specification including code generation for its sister specification Concise Data Definition Language (CDDL) |
Oh and one last one that I would really love to see although I don’t know it fits the idea of a language or even tooling change more just something that I think is missing from the ecosystem which is a good RDF (Resource Description Framework) library. After many years of work the newest version is due to be finalized quite soon I believe. It’s a hugely popular and powerful way to model data in an interoperable and language neutral way and would pair incredibly well with a lot of the AI work Google is bringing to Flutter and elsewhere. |
Thanks @bivens-dev ... what would core language support for RFC8949 look like? I mean, compared to just doing it with codegen. Technical suggestions for specific things we could do/support are useful, thanks; it'd also be good to hear about specific use cases that don't work well today that would benefit. |
Thanks for the clarifying question. Reading it back now I agree the phrase "core language support" is incredibly ambiguous, my apologies for that. Specifically what I mean in the case of That would be independent of the Concise Data Definition Language (CDDL) point I mentioned which I guess is the CBOR equivalent of a protobuf file / language and is what would be used as the basis of the code generation. I would probably also make a similar argument for RDF in that I think it is already seeing incredibly strong adoption not just among businesses but also amongst governments. Some examples of that might include the Australian Government Linked Data Working Group and European Union's Linked Open Data. Right now, I'm not really aware of any good solutions for working with RDF data at all within the Dart community and that too feels like something that will become a real problem before too long. Once again, I would make the same argument that given the level of trust people and organizations are going to need around a topic like that, community support doesn't feel like an appropriate option. I think in concrete terms it too would ultimately look like a library that in addition to providing Dart native representations of key concepts like graphs, tuples, resources etc would also include a Codec to convert to and from the most common serialization formats. Hopefully, that helps clarify things a bit more and generally provide some additional context as to why I think they are important both in terms of capabilities but also why I think they need certain quality guarantees that I don't think can actually come from the community at this time. [1] My understanding of this is that CDDL is now the new defacto standard for representing data types and has been for some time already for all IETF standards. Some relevant examples using CBOR that immediately come to mind both from IETF and others include:
|
In case it wasn't on the radar yet: https://github.com/schultek/codable |
Re: "tooling improvements", I plan on working on build_runner performance: dart-lang/build#3800 |
ORs need the record treatment! What? Well one of the problems addressed by records is that if you decide "actually this function should return this type AND this other type" then you had to make a new class, which was a pretty steep syntatic cliff. Currently, if you decide "actually this function should return this type OR this other type" then you make a sealed hierarchy of classes, which is a similarly steep cliff. I don't think this needs a super powerful solution like (untagged) union types. IMO the desirable property of union types for most people is not that they save you from having to pick a name for each variant, but that the syntax is concise and inline. One of the things I was planning on using macros for was seeing how concise I could make the syntax for defining what would eventually generate a sealed hierarchy of classes. I think the most relevant issues are #3021 and #2364 but those both still require writing new top-level definitions - the ideal would be writing it inline. For example: // strawman syntax
.ConnectResult(.AuthExpired | .Offline | .Success({bool stable, Connection connection})) connect() {
}
// would internally generate
sealed class ConnectResult {}
class AuthExpired implements ConnectResult {}
class Offline implements ConnectResult {}
class Success implements ConnectResult {
final bool stable;
final Connection connection;
Success({required this.stable, required this.connection});
} |
one of the key benefits of sum types is you can evolve an api without breaking changes today: future: |
// strawman syntax
.ConnectResult(.AuthExpired | .Offline | .Success({bool stable, Connection connection})) connect() {
} This is functionally equivalent to rust's enums. Sum types like (A | B) have their uses, too - one doesn't exclude the other. |
Widening the parameters of an instance method is breaking if there is any subclass implementing the narrower parameter type. Changing an instance member signature to a subtype is breaking for subclasses. |
^ That's arguable. If we think about it for long enough, almost everything is breaking in some capacity. For example, technically speaking modifying any function prototype is breaking ; even if they don't belong to a class/interface, because of type-inference. Say a package makes such change: -void function(String input) {};
+void function(String? input) {}; This would break apps that do: final callbacks = [function];
callback.add((value) => print(value[0])); But realistically, nobody does that. The same applies to class methods IMO. |
I might be colored by working on the platform libraries, where we can usually assume that anything a user can do, someone does. There are classes that were never intended as interfaces, and methods that were never intended to be overridden in an extending subclass. Widening the parameter type of such a function on such a class can probably be ruled to be "non-breaking in practice". That's what the Dart breaking change process is for, deciding whether a breaking change is expected to be actually breaking on a significant scale. (Doesn't help us if it actually breaks something anyway.) But, getting back on track, union types won't help if a change of actually breaking. They're just a wider parameter type. |
And you also don't need general union types to evolve an api without breaking changes - i.e Records were great because they added an intermediate step in power. Perfect for when you don't need all the capabilities of a full blown class (constructors, inheritance, methods, mutable state, etc) - you need to It would be nice if there was a similar intermediate step before "write out a sealed class hierarchy" for when you just need to General union types are definitely a solution, but IMO they're unnecessarily powerful for this specific problem to justify their cost. That's why I was thinking of something that has the nice concise inline "structural" syntax of union types, but would desugar to a sealed class hierarchy. Similar to how records are more or less syntax sugar for simple classes (runtime considerations notwithstanding). |
While having sum type / Rust-like enum would certainly be great, honestly I find it more painful at the moment to have to resort to codegen (e.g., with Besides, I think it would be nice to have things like these built natively (or included in the standard library), like the path that Go took with struct tag, |
We'd like to make some combination of language and tooling improvements to better support serialization & data modeling.
More details to follow. We'll be asking for input on what people want to see--those interested can watch this issue for updates.
The text was updated successfully, but these errors were encountered: