-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Allow EfficientLengthIterable equivalent for non-SDK libraries #29862
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
There really is not a good way to introduce this feature. What we do not want is anyone, ever, writing So, the answer for #23328 stands for now - use Hmm, perhaps we could expose an We'll think about it, but it's not high on the list of 2.0 features. |
Hmm. Actually I think I have a workaround. I don't want to implement List/Set/Queue because they carry methods that I won't implement. (The Java/Guava route for immutable collections). But I can do this:
That means I get the static checks I want. At runtime, instances will be EfficientLengthIterable via List. This does mean that if anyone is doing processing based on the runtime type and checking for List they may be surprised ... but I can't see that being particularly important. WDYT? Do you see any downsides to doing this? Thanks! |
My workaround is slightly less nice than hoped :/ ... because But I can use/abuse Benchmarking List#addAll(new BuiltList(...lots of data)) shows a 2x speedup, as you would expect -- it can straight away grow the list by the right amount. @lrhn it's not pretty but I think I can live with this. What do you think, please? |
I think it's an extremely ugly hack, but I can also see that we are not giving you a better alternative. I'll consider whether to expose a subclass of Maybe (and definitely no promises): class EfficientLengthIterable implements _internal.EfficientLengthIterable {
factory EfficientLengthIterable._cannotBeExtendedOrInstantiated() => null;
static bool isEfficient(Iterable iterable) => iterable is _internal.EfficientLengthIterable;
} That would allow meBeingTooCleverByHalf(Iterable iter) {
assert(EfficientLengthIterable.isEfficient(iter));
...
} but we can't prevent all self inflicted wounds like that, just recommend that they say |
What about splitting
There's then no point in writing
because you can't do anything useful with it. |
That's what we had before. (Not publicly exposed, but still). We merged them, because least-upper-bound computations found Already at that time, we debated, if we should expose We are now wondering, if we can reduce the need for it. Most of the time, when we use it, is because the API accepts an |
There probably aren't too many important uses, but |
When we had |
What do you think about using an annotation as a marker? import 'dart:collection' show efficientLength;
@efficientLength
class BuiltList<E> implements Iterable<E> { ... } |
@pschiffmann I don't think an annotation helps -- there's no way to check for it given an instance of that type. |
After reading lrhn's last comment I thought thats' what he wanted. And trying to look at it from that perspective, it made sense to me: Instantiating user-written data structures (trees, linked lists) from the Iterable is done one node at a time; sequential map/filter/reduce don't care about length; and parallel stuff requires a proper Please don't get me wrong, I'm not trying to sell you my idea here. I just got more and more interested in language design recently and just saw a change to contribute my first idea ;-) So if you'd take the time to point out my thought flaws and teach me something in the process, I'd be very thankful! |
Ah, I see what you mean -- yes, I guess the SDK could do something special to allow just blessed code to check for it at runtime. Interesting. I don't work on the SDK though, so my opinion doesn't count for much :) ... @lrhn what do you think please? For the record, there are currently 5 places in the SDK using "is EfficientLength": array_patch.dart, growable_array.dart, string_patch.dart, queue.dart and iterable.dart. |
The We tried making it public so a class could mark itself as having efficient length, but the uses of it weren't encouraging (using it as a type, having functions expecting an So, no, there is no current plan to make the feature generally available. We definitely do not want annotations to mean anything to the platform libraries at runtime. If it's important at runtime, it should be reflected in the runtime objects. |
Perhaps as a slightly different version of this request, I'd like to have a
There's a fairly common source of confusion when you get used to working with void myFunction<T>(Iterable<T> iterable) {
print(iterable.length); // 5
print(iterable.length); // 0!
print(iterable.first); // exception? null? certainly not the first element at the start of this method.
} It would be helpful to have a SDK type that could be passed in instead like |
Also as a type implementer, I'd like to impelement things sometimes that are basically lists but do not derive from list. |
We are not planning on introducing any public marker interface for classes having efficient length, contains, last, etc. |
See #23328 for context; the SDK uses EfficientLengthIterable to decide whether an Iterable is backed by something that can quickly return "length". Because non-SDK libraries cannot access EfficientLengthIterable they are always treated as not having efficient "length", leading to extra work.
It's not clear what could be done to fix this, but if there's any way to do it with 2.0, that would be great.
The text was updated successfully, but these errors were encountered: