Skip to content
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

DART 3 Records Feature Requirement: Can it provide introspection capabilities similar to enum.values #2826

Closed
chen56 opened this issue Feb 7, 2023 · 2 comments
Labels
feature Proposed language feature that solves one or more problems state-rejected This will not be worked on

Comments

@chen56
Copy link

chen56 commented Feb 7, 2023

const tree=(
  a:"/a",
  b:"/b",
    c:(
        a:"/c/a",
        b:"/c/b",
    ),
);

make records work same as a Map?

print(tree.keys);// [a,b,c]
print(tree["a"]);// "/a"

or may be like a array?

print(tree.length);// 3
print(tree.$1);// /a
print(tree[0]);// /a

I Read #2673 , but,I don't know how enum.values do it. Can it be implemented similarly?

This is very useful for implementing static variable trees,
now dart is very inconvenient,like this:

N<void> root = N<void>("/", meta: rootPage, kids: [
  N<void>("not_found", meta: notFoundPage),
  N<void>("note", meta: notePage, kids: [
    N<void>("material", kids: [
    ]),
  ]),
]);

N page(path) => root.kid(path);

class Paths {
  final N<void> home = page("/");
  final N<void> notFound = page("/not_found");
  final N<void> note = page("/note");
  final N<void> note_material = page("/note/material");

  Paths._();
}

var paths = Paths._();
@chen56 chen56 added the feature Proposed language feature that solves one or more problems label Feb 7, 2023
@chen56 chen56 changed the title DART 3 Records Feature Requirement: Can it provide introspection capabilities similar to Enum.Values DART 3 Records Feature Requirement: Can it provide introspection capabilities similar to enum.values Feb 7, 2023
@lrhn
Copy link
Member

lrhn commented Feb 8, 2023

Records are not like maps or lists. Instead records are treated (somewhat) as if each record shape was its own generic class. The record fields are getters, and record types with different shapes are unrelated types.

You can't ask a class for its field names, and even if you could, you can't use it for anything since you can't use a string to access a class field. You need to write the field access into in the source code.

That allows the compiler to throw away member names at runtime, source names are not needed at runtime, they are resolved during compilation.

Records work the same way. You can't ask a record for its shape, you can only compare it to shapes that you already know about. If you don't know the shape, all you can do is dynamic member access, just like on other objects.
If all you know about a value is that it's a Record, it's not much more useful than knowing that it's an Object. All it does is rule out non-record types as being possible runtime types for the object, but that doesn't help much more than knowing that an Object is not a List. You still need to know what it is to use it.

Not allowing introspection is a deliberate choice.

Introspection is reflection. Reflection has a cost in source information needed at runtime, and it affects tree-shaking, so it's a double-whammy for ahead-of-time compiled code. That's also the reason we do not support dart:mirrors in ahead-of-time compiled code.
It's also potentially slow, like dynamic invocations.

It means we cannot, for example, parse JSON into records with the same structure, because we can only create shapes that existed in the source code originally.

If you define a large record structure, like:

var data = (version: "4.2", elements: [
   (name: "foo", price: 369),
   (name: "bar", price: 420),
]);

then you have that structure, with its specific type, but it's really not much different from having:

var data = Data(version: "4.2", elements: [
   Element(name: "foo", price: 369),
   Element(name: "bar", price: 420),
]);

for suitably declared classes. You just get the "class" for free, at the cost of not having any methods or documentation.

If you want to build structures that allow introspection, you should create classes which themselves provide that functionality. I'm sure macros will be useful to build such classes.

@lrhn lrhn closed this as completed Feb 8, 2023
@lrhn lrhn added the state-rejected This will not be worked on label Feb 8, 2023
@chen56
Copy link
Author

chen56 commented Feb 10, 2023

@lrhn Thank you for your detailed explanation. I understand. It seems that similar scenarios only can be solved by automatically generating code or enum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems state-rejected This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants