Skip to content

Commit

Permalink
Add Keyword.get_and_update/3
Browse files Browse the repository at this point in the history
I added the `get_and_update/3` function to the `Keyword` module. I also added
tests for this function, docs (with doctests) and specs.
  • Loading branch information
whatyouhide committed Jan 27, 2015
1 parent 69b029f commit eb60b06
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 16 deletions.
58 changes: 42 additions & 16 deletions lib/elixir/lib/keyword.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,32 @@ defmodule Keyword do
end
end

@doc """
Gets the value from `key` and updates it, all in one pass.
This `fun` argument receives the value of `key` (or `nil` if `key`
is not present) and must return a two-elements tuple: the "get" value (the
retrieved value, which can be operated on before being returned) and the new
value to be stored under `key`.
The returned value is a tuple with the "get" value returned by `fun` and a new
keyword list with the updated value under `key`.
## Examples
iex> Keyword.get_and_update [a: 1], :a, fn(current_value) ->
...> {current_value, "new value!"}
...> end
{1, [a: "new value!"]}
"""
@spec get_and_update(t, key, (value -> {value, value})) :: {value, t}
def get_and_update(keywords, key, fun) when is_list(keywords) and is_atom(key) do
current_value = get(keywords, key)
{get, new_value} = fun.(current_value)
{get, put(keywords, key, new_value)}
end

@doc """
Fetches the value for a specific `key` and returns it in a tuple.
Expand All @@ -145,8 +171,8 @@ defmodule Keyword do
end

@doc """
Fetches the value for specific `key`.
Fetches the value for specific `key`.
If `key` does not exist, a `KeyError` is raised.
## Examples
Expand Down Expand Up @@ -186,8 +212,8 @@ defmodule Keyword do
end

@doc """
Returns all keys from the keyword list.
Returns all keys from the keyword list.
Duplicated keys appear duplicated in the final list of keys.
## Examples
Expand Down Expand Up @@ -325,8 +351,8 @@ defmodule Keyword do
end

@doc """
Checks if two keywords are equal.
Checks if two keywords are equal.
Two keywords are considered to be equal if they contain
the same keys and those keys contain the same values.
Expand All @@ -342,8 +368,8 @@ defmodule Keyword do
end

@doc """
Merges two keyword lists into one.
Merges two keyword lists into one.
If they have duplicated keys, the one given in the second argument wins.
## Examples
Expand All @@ -359,8 +385,8 @@ defmodule Keyword do
end

@doc """
Merges two keyword lists into one.
Merges two keyword lists into one.
If they have duplicated keys, the given function is invoked to solve conflicts.
## Examples
Expand Down Expand Up @@ -402,8 +428,8 @@ defmodule Keyword do
end

@doc """
Updates the `key` with the given function.
Updates the `key` with the given function.
If the `key` does not exist, raises `KeyError`.
If there are duplicated keys, they are all removed and only the first one
Expand Down Expand Up @@ -436,8 +462,8 @@ defmodule Keyword do
end

@doc """
Updates the `key` with the given function.
Updates the `key` with the given function.
If the `key` does not exist, inserts the given `initial` value.
If there are duplicated keys, they are all removed and only the first one
Expand Down Expand Up @@ -467,8 +493,8 @@ defmodule Keyword do

@doc """
Takes all entries corresponding to the given keys and extracts them into a
separate keyword list.
separate keyword list.
Returns a tuple with the new list and the old list with removed keys.
Keys for which there are no entires in the keyword list are ignored.
Expand Down
12 changes: 12 additions & 0 deletions lib/elixir/test/elixir/keyword_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ defmodule KeywordTest do
assert Keyword.get(create_empty_keywords, :first_key, "default") == "default"
end

test "get_and_update/3" do
{get, new_keywords} = Keyword.get_and_update(
create_keywords,
:first_key,
fn(current_val) -> {current_val, "foo"} end
)

assert get == 1
assert Keyword.get(new_keywords, :first_key) == "foo"
assert Keyword.get(new_keywords, :second_key) == 2
end

test "fetch!/2" do
assert Keyword.fetch!(create_keywords, :first_key) == 1

Expand Down

0 comments on commit eb60b06

Please sign in to comment.