@@ -867,6 +867,40 @@ defmodule Keyword do
867867 raise KeyError , key: key , term: original
868868 end
869869
870+ @ doc """
871+ Replaces the value under `key` using the given function only if
872+ `key` already exists in `keywords`.
873+
874+ In comparison to `replace/3`, this can be useful when it's expensive to calculate the value.
875+
876+ If `key` does not exist, the original keyword list is returned unchanged.
877+
878+ ## Examples
879+
880+ iex> Keyword.replace_lazy([{:a, 1}, {:b, 2}], :a, fn v -> v * 4 end)
881+ [{:a, 4}, {:b, 2}]
882+
883+ iex> Keyword.replace_lazy([{:a, 1}, {:b, 2}], :c, fn v -> v * 4 end)
884+ [{:a, 1}, {:b, 2}]
885+
886+ """
887+ @ doc since: "1.14.0"
888+ @ spec replace_lazy ( t , key , ( existing_value :: value -> new_value :: value ) ) :: t
889+ def replace_lazy ( keywords , key , fun )
890+ when is_list ( keywords ) and is_atom ( key ) and is_function ( fun , 1 ) do
891+ do_replace_lazy ( keywords , key , fun )
892+ end
893+
894+ defp do_replace_lazy ( [ { key , value } | keywords ] , key , fun ) do
895+ [ { key , fun . ( value ) } | delete ( keywords , key ) ]
896+ end
897+
898+ defp do_replace_lazy ( [ { _ , _ } = e | keywords ] , key , fun ) do
899+ [ e | replace_lazy ( keywords , key , fun ) ]
900+ end
901+
902+ defp do_replace_lazy ( [ ] , _key , _value ) , do: [ ]
903+
870904 @ doc """
871905 Checks if two keywords are equal.
872906
0 commit comments