-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Dart enum toString is too verbose #30021
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
Comments
Using As for enums, the Dart enum design is very plain, enum instances are not carrying any value except their distinguishing index, and that includes a string of their source name. Their It seems that you actually do want a string that matches their declared name, and even as a string, not a symbol. That's two steps removed from the actual declaration, and not something that is generally desirable. That said, we did chose to provide the name in the |
To clarify, Flutter uses the short name as part of debugging messages so symbolizing names in production would probably be acceptable. The debugging messages can get very large and need to be easy to read so showing the class name as well as the entry name doesn't work. I agree that adding a To avoid a breaking change we could add a top level method to the core library that gets the name of an enum entry. E.g. Using a more verbose name would also be reasonable. We can track the number of occurrences of the verbose name in pub packages to verify the impact of the breaking change will be small. For example, I would guess than |
1. I would like to avoid symbolizing anything - in dart2js, the symbols
cause allocations at startup.
2. Minified dart2js output contains many copies of the enum class name
embedded in the 'name' strings, e.g. "Day.monday", "Day.tuesday" etc. The
"${entry.runtimeType}.$entry" approach would print minified types, e.g
"z6.monday"
3. The VM misses an opportunity to 'safe-print' enum names. For example,
d.cancel() prints
NoSuchMethodError: Class 'Day' has no instance method 'cancel'
Receiver: Instance of 'Day'
but could 'safe-print' enum values instead of or in addition to "Instance
of 'Day'"
4. dart2js could also safe-print enum values.
…On Tue, Jun 27, 2017 at 9:13 AM, Jacob Richman ***@***.***> wrote:
To clarify, Flutter uses the short name as part of debugging messages so
symbolizing names in production would probably be acceptable. The debugging
messages can get very large and need to be easy to read so showing the
class name as well as the entry name doesn't work.
I agree that adding a name getter is bad for the reasons you suggest.
To avoid a breaking change we could add a top level method to the core
library that gets the name of an enum entry. E.g. enumEntryName(Object o)
Using a more verbose name would also be reasonable. We can track the
number of occurrences of the verbose name in pub packages to verify the
impact of the breaking change will be small. For example, I would guess
than toStringShort is not used as an enum entry in any existing package.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#30021 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACAtleaXl8hkUmnBpHo46m1x5p7FbXElks5sISoZgaJpZM4OF62f>
.
|
We don't make it easy to recognize enum values as being so. There is no common type that enum classes evaluate to (unlike, say, Java where |
Implementing an explicit Enum interface would help a lot. I don't think we
lose much by defining an explicit Enum type as enums as defined now are
already too typed to work well for JS interop. For js interop you would
want enum values to just be int or string.
@lrhn wrote:
…We don't make it easy to recognize enum values as being so. There is no common type that enum classes evaluate to (unlike, say, Java where `enum Foo` implements `Enum<Foo>`).
If we did that, it's likely that `Error.safeToString` or similar methods could handle enums as well without needing a platform hook to recognize it as safe.
|
What are the benefits of the type parameter in |
Looking at the Java implementation, the only two methods on
We don't need the Another use-case of generic classes in general is to restrict to a sub-hierarchy ( We could just make enum a non-generic class that declares So, unless we intend to add methods to bool operator <(covariant Enum other); // in Enum and override it in each implementation (or cheat, since we probably don't allow anybody to implement |
This also comes up with Intl. There's a select method that lets you choose from several alternatives. It's a natural fit for enums, but it's defined to accept only certain characters in select identifiers, and excludes ".". We could transform the result of the enum's toString(), but that gets pretty ugly. |
Here is another way to do the conversion:
|
This is really asking for a way to get just the name of the enum, so it's a duplicate of dart-lang/language#1511. |
I just made a package for this... https://pub.dev/packages/enum_to_string Pretty simple and welcome and pull requests! |
Late to the party, but I thought I'd share this solution in case it helps others. I settled for defining a "toText" extension method to accompany my enum. This allowed me to perform whatever logic I wished a "toString" override might perform. In my case, I wanted to exclude the type specifier and translate underscores to spaces, so it looked like the following:
This allowed for:
FWIW, worked great for me. |
I solved enum to string conversion like this:
🎉 |
It's really unfortunate we have to manually write this code for every enum we declare, and what about fromString? That is the much more verbose one. Even using a package, I have to write:
Ideally it should just be like this:
I'm surprised this is closed with such a cludgy workaround for such a core feature of the language. Why make developers pass around .value when the compiler already knows it, or write the exact same |
Can we have this native now with enum having a supertype in Dart 2.14? |
I'm still philosophically opposed to exposing source names at runtime. (I wish someone would have [written a warning] about exposing properties of an object only in its |
@lrhn How do you serialize/deserialize enums without knowing their names? |
@jolleekin Lots of ways are possible. You can use the If you intend to interact with other languages, you need a shared dictionary anyway. The word used there doesn't need to be the Dart name. If the serialization key is |
I think you should search for how many open source dart projects have describeEnum to see if this is really popular/necessary. I think so, but maybe no one ever uses it... |
I disagree with the whole index serialization philosophy, Counterpoint: the position of the enum in the list should be irrelevant, the "name" (i.e. content or intent) is what makes it meaningful.
I guess I'm arguing for a |
I think the real truth is that both approaches are valid. There are times where serializing by index is more robust or well suited to your data, other times you want them stored as values for whatever reason. C# allows both, and developers use both, depending on circumstances. There's no point arguing whether an orange tastes better than an apple. Generally speaking, serializing by value works better when you have a very large set of enums, that are constantly gaining new entries, (think collectable items in an a game). I can't have serialization breaking each time I add an item, and because of the huge set of items, I want to keep things alphabetically sorted, not just tack them on to the end of the enum in random order. So names is much nicer to work with here, because order is irrelevant. In another case, where I have fewer items, I don't care as much about alphabetical sorting, and I want to instead prioritize the ability to easily rename any of the items to enhance readability in my codebase. Then index based works better because value is irrelevant. In either case serializing enums is brittle, and it always will be. But the developer is in the best place to decide which is least brittle for their dataset. |
Serialization means a lot of things. Here we're talking about storage of the serialized data which spans multiple program versions, all written in Dart. That's a finnicky thing to go for, the result might not make sense at all if you end up removing elements from the enum. You need to properly version your storage format. Using a string to represent the enum value is perfectly fine, but it doesn't have to be the source name from the enum declaration. Other serialization options are between different instances of the same version of the program (any consistent serialization works), or between completely different programs which may not even be written in the same language (you need a completely specified communication protocol down to the byte level). For You really want something like Java's enum declarations: enum MyEnum {
yes("Yes"),
no("No"),
maybe("Maybe");
final String serializationID;
MyEnum(this.serializationID);
} Focusing on access to the source name as a string is a red herring, when we should be focusing on how to store more information on the enum instead. That'd work with anything, and would not depend on coding style for the enum constant names. |
I think when you get into advanced scenarios like that, enums are not really worth their weight. It's better to just use strings, or ints, and KISS by using a primitive that easily crosses language boundaries. The main issue here that needs addressing imo, is just basic serialization of enums in dart, which is overly cludgy. |
Starting on Dart 2.15 now it can. There is |
Flutter can't use the default
toString()
for enum types as it is too verbose and instead has to carefully call adescribeEnum(entry)
helper whenever an enum entry is displayed in a message.The describeEnum helper strips out the enum type from the result of calling
entry.toString()
.It would be nice if the default toString() for enum just displayed the enum value or if the enum class provided a
toStringShort()
method that returned just the enum value.Note that you someone who really wanted to display Type.entry could just write
'${entry.runtimeType}.${entry}'
Example of current behavior:
The text was updated successfully, but these errors were encountered: