]> git.lizzy.rs Git - rust.git/commitdiff
Add or_insert_with_key to Entry of HashMap/BTreeMap
authorChai T. Rex <ChaiTRex@users.noreply.github.com>
Fri, 10 Apr 2020 16:10:05 +0000 (12:10 -0400)
committerChai T. Rex <ChaiTRex@users.noreply.github.com>
Fri, 10 Apr 2020 16:54:09 +0000 (12:54 -0400)
Going along with or_insert_with, or_insert_with_key provides the
Entry's key to the lambda, avoiding the need to either clone the
key or the need to reimplement this body of this method from
scratch each time.

This is useful when the initial value for a map entry is derived
from the key. For example, the introductory Rust book has an
example Cacher struct that takes an expensive-to-compute lambda and
then can, given an argument to the lambda, produce either the
cached result or execute the lambda.

src/liballoc/collections/btree/map.rs
src/libstd/collections/hash/map.rs

index a1e59b2e6afb33220cfb22c4938339725ee2f080..650582850ab964c6c9380f68448ce025469355d2 100644 (file)
@@ -2378,6 +2378,33 @@ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         }
     }
 
+    #[unstable(feature = "or_insert_with_key", issue = "70996")]
+    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
+    /// which takes the key as its argument, and returns a mutable reference to the value in the
+    /// entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    ///
+    /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count());
+    ///
+    /// assert_eq!(map["poneyland"], 9);
+    /// ```
+    #[inline]
+    pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
+        match self {
+            Occupied(entry) => entry.into_mut(),
+            Vacant(entry) => {
+                let value = default(entry.key());
+                entry.insert(value)
+            }
+        }
+    }
+
     /// Returns a reference to this entry's key.
     ///
     /// # Examples
index d1cb8e92d5688a9af19c95dba6aa14775a675355..277b37dd310436e2ce7ba481a0aaa587e49d54f2 100644 (file)
@@ -1943,6 +1943,33 @@ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         }
     }
 
+    #[unstable(feature = "or_insert_with_key", issue = "70996")]
+    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
+    /// which takes the key as its argument, and returns a mutable reference to the value in the
+    /// entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, usize> = HashMap::new();
+    ///
+    /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count());
+    ///
+    /// assert_eq!(map["poneyland"], 9);
+    /// ```
+    #[inline]
+    pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
+        match self {
+            Occupied(entry) => entry.into_mut(),
+            Vacant(entry) => {
+                let value = default(entry.key());
+                entry.insert(value)
+            }
+        }
+    }
+
     /// Returns a reference to this entry's key.
     ///
     /// # Examples