dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.06k stars 1.55k forks source link

Map should have a method to retrieve a value but throws if the value is not present. #6640

Open alan-knight opened 11 years ago

alan-knight commented 11 years ago

The current implementation of putIfAbsent in ImmutableMap is

  V putIfAbsent(K key, V ifAbsent()) {     throw new UnsupportedError("Cannot set value in unmodifiable Map");   }

I'd prefer it if it actually called the ifAbsent function before that. My use case is that I have a method   externalObjectNamed(key) => externalObjects.putIfAbsent(key, () =>       throw 'Cannot find named object to link to: $key');

which is conveniently easy to write compared to doing an indexing operation and checking the result for null. But it cannot be used if the map is immutable.

lrhn commented 11 years ago

I don't think we'd want this. It's clever use of putIfAbsent, but not its intended use. If you use a put operation on an unmodifiable collection or map, you are doing something wrong. In a less dynamic language it would be a type error, and we want to fail early on this.


cc @floitschG.

floitschG commented 11 years ago

I agree with Lasse, invoking a mutating method on an immutable map should throw as early as possible.

What you actually want is a method that retrieves a value, but throws if the value is not there. This is not something I'm immediately opposed to. Changing the summary accordingly.


Changed the title to: "Map should have a method to retrieve a value but throws if the value is not present.".

DartBot commented 11 years ago

This comment was originally written by @alan-knight


Yes, some kind of general ifAbsent method would be better in this case. Rather than having one that throws if the value isn't there, it would be nice if, like putIfAbsent, it could evaluate an arbitrary function. That could be used to throw if the value wasn't there, but also to return a default value if the value wasn't there, or other variations.

dgrove commented 11 years ago

Removed Library-Collections label. Added Library-Collection label.

lrhn commented 11 years ago

The analogue to putIfAbsent would be "getOrElse" (really bad name, but I like the vaguely menacing sound of it :).

  V getOrElse(K key, V fallback()) {     .. do internal lookup ..;     if (...not there...) return fallback();     return ... value of lookup ...;   }    


Removed Type-Defect label. Added Type-Enhancement label.