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
Consider "asList", "asMap", and "asSet" #77
Comments
It's possible -- I'm not quite clear on how asList is better than toList, though. The current toList is implemented using a copy-on-write wrapper, so it's cheap to create unless you actually then mutate it. So we have: toList: fast, when you do a mutate, does a copy the first time If the second is preferable in some cases, sure, we can add it. FWIW, I try to pass around Iterable where possible. I think this is generally good practice. There are others who believe that Iterable should be used carefully because it might be a lazy iterable ... but for me, it's the people passing around lazy iterables who need to be careful, and the rest of us should use Iterable where possible as it's a nice interface. Unfortunately there's no equivalent for map. (Iterable of values plus a lookup function is what I sometimes use in practice, but that's pretty horrible.) |
Really this is somewhere I wish we had a good zero-cost abstraction around a mutable list we don't want anyone to modify - perhaps something where asList() {
var list = _backingList;
assert(() {
list = new List<T>.unmodifiable(list);
});
return list;
} |
Well -- we can do better here. new List.unmodifiable copies the list, but actually within BuiltList we know the list will not be modified. So we could return a wrapper that throws on modify, like the current wrapper that copies on modify. The question is whether the throw behaviour is really a useful thing to have :) |
That's fair. I think I like having the throw behavior for developers to get failures when they use your API: external Map getEmployeeMap();
void main() {
// Throws StateError, due to the Map being returned being unmodifiable.
getEmployeeMap().clear();
} |
Hmm. For that example I think not throwing is better, then you can do e.g.: final map = getEmployeeMap(); But maybe there are others where it's weird to let you mutate (well, appear to mutate) the collection? ... I guess that would be if you then assume the changes you make have an "action at a distance" effect on something: final map = getEmployeeMap(); But for me that would be a surprising thing to do. Not sure. What do you think? |
I think copy on write at least gives the API producer safety, but the consumer will need to read the API documentation to know changes they are making effectively do nothing. That being said, I was more concerned about API producer side, so maybe this isn't a real priority for now. |
I think it does make sense to have both, to give people a choice. This should be trivial to implement, we can use UnmodifiableListView/UnmodifiableSetView/UnmodifiableMapView. |
I like this library, but one thing stopping me from using it is that I don't want to require other users to use
built_collection
, so I tend to only use it as an implementation detail and pass atoList/toMap/toSet
as part of my API.I would use
asList/Map/Set
, where they could be, for example:The text was updated successfully, but these errors were encountered: