         end) |> elem(1)
       end
 
+      def update(dict, key, initial, fun) do
+        case fetch(dict, key) do
+          { :ok, value } ->
+            put(dict, key, fun.(value))
+
+          :error ->
+            put(dict, key, initial)
+        end
+      end
+
+      def update!(dict, key, fun) do
+        case fetch(dict, key) do
+          { :ok, value } ->
+            put(dict, key, fun.(value))
+
+          :error ->
+            raise KeyError, key: key, term: dict
+        end
+      end
+
+      def pop(dict, key, default \\ nil) do
+        case fetch(dict, key) do
+          { :ok, value } ->
+            { value, delete(dict, key) }
+
+          :error ->
+            { default, dict }
+        end
+      end
+
       defoverridable merge: 2, merge: 3, equal?: 2, to_list: 1, keys: 1,
                      values: 1, take: 2, drop: 2, get: 2, get: 3, fetch!: 2,
-                     has_key?: 2, put_new: 3
+                     has_key?: 2, put_new: 3, pop: 2, pop: 3, update: 4, update!: 3
     end
   end
 end

  * `keys/1`
  * `merge/2`
  * `merge/3`
  * `put_new/3`
  * `take/2`
  * `to_list/1`
  * `values/1`

  All of these functions are defined as overridable, so you can provide your own
  implementation if needed.


        # implement required functions (see below)

        # override default implementations if optimization is needed
      end

  The client module must contain the following functions:
