Elixir语言中 Kernel.get_and_update_in
相关用法介绍如下。
用法一
get_and_update_in(path, fun)
(宏)
通过给定的 path
获取值并更新嵌套数据结构。
这类似于
,除了路径是通过宏提取而不是传递列表。例如:get_and_update_in/3
get_and_update_in(opts[:foo][:bar], &{&1, &1 + 1})
相当于:
get_and_update_in(opts, [:foo, :bar], &{&1, &1 + 1})
这也适用于嵌套结构和 struct.path.to.value
指定路径的方式:
get_and_update_in(struct.foo.bar, &{&1, &1 + 1})
请注意,为了使此宏工作,完整路径必须始终对此宏可见。请参阅下面的"Paths" 部分。
例子
iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users["john"].age, &{&1, &1 + 1})
{27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}
路径
路径可以以变量、本地或远程调用开始,并且必须后跟一个或多个:
-
foo[bar]
- 访问foo
中的 keybar
;如果foo
为 nil,则返回nil
-
foo.bar
- 访问映射/结构字段;如果该字段不存在,则会引发错误
以下是一些有效路径:
users["john"][:age]
users["john"].age
User.all()["john"].age
all_users()["john"].age
以下是一些无效的:
# Does a remote call after the initial value
users["john"].do_something(arg1, arg2)
# Does not access any key or field
users
用法二
get_and_update_in(data, keys, fun)
@spec get_and_update_in(
structure,
keys,
(term() | nil -> {current_value, new_value} | :pop)
) :: {current_value, new_structure :: structure}
when structure: Access.t(),
keys: [any(), ...],
current_value: Access.value(),
new_value: Access.value()
获取一个值并更新一个嵌套结构。
data
是一个嵌套结构(即实现
行为的映射、关键字列表或结构)。Access
fun
参数接收 key
的值(或 nil
,如果 key
不存在)并且必须返回以下值之一:
-
一个二元素元组
{current_value, new_value}
。在这种情况下,current_value
是检索到的值,可以在返回之前对其进行操作。new_value
是要存储在key
下的新值。 -
:pop
,这意味着key
下的当前值应从结构中删除并返回。
此函数使用
模块根据给定的 Access
keys
遍历结构,除非 key
是一个函数,这将在后面的部分中详细介绍。
例子
当需要检索当前值(或根据当前值计算的值)并同时更新它时,此函数很有用。例如,它可以用于读取用户的当前年龄,同时将其增加一倍:
iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users, ["john", :age], &{&1, &1 + 1})
{27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}
请注意,赋予匿名函数的当前值可能是 nil
。如果任何中间值为零,它将引发:
iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users, ["jane", :age], &{&1, &1 + 1})
** (ArgumentError) could not put/update key :age on a nil value
作为键的函数
如果键是一个函数,该函数将被调用并传递三个参数:
- 操作(
:get_and_update
) - 要访问的数据
- 接下来要调用的函数
这意味着可以扩展
以提供自定义查找。缺点是函数不能作为键存储在访问的数据结构中。get_and_update_in/3
当其中一个键是函数时,调用该函数。在下面的示例中,我们使用一个函数来获取和递增列表中的所有年龄:
iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}]
iex> all = fn :get_and_update, data, next ->
...> data |> Enum.map(next) |> Enum.unzip()
...> end
iex> get_and_update_in(users, [all, :age], &{&1, &1 + 1})
{[27, 23], [%{name: "john", age: 28}, %{name: "meg", age: 24}]}
如果调用函数之前的前一个值是 nil
,则函数 will
接收 nil
作为值并且必须相应地处理它(无论是失败还是提供合理的默认值)。
模块附带许多便利访问器函数,例如上面定义的Access
all
匿名函数。请参阅
、 Access.all/0
和其他示例。Access.key/2
相关用法
- Elixir Kernel.get_in用法及代码示例
- Elixir Kernel.SpecialForms.case用法及代码示例
- Elixir Kernel.round用法及代码示例
- Elixir Kernel.left / right用法及代码示例
- Elixir Kernel.put_in用法及代码示例
- Elixir Kernel.tl用法及代码示例
- Elixir Kernel.left - right用法及代码示例
- Elixir Kernel.tuple_size用法及代码示例
- Elixir Kernel.defexception用法及代码示例
- Elixir Kernel.to_charlist用法及代码示例
- Elixir Kernel.base ** exponent用法及代码示例
- Elixir Kernel.left !== right用法及代码示例
- Elixir Kernel.if用法及代码示例
- Elixir Kernel.spawn_monitor用法及代码示例
- Elixir Kernel.to_string用法及代码示例
- Elixir Kernel.length用法及代码示例
- Elixir Kernel.first..last用法及代码示例
- Elixir Kernel.SpecialForms.%{}用法及代码示例
- Elixir Kernel.SpecialForms.for用法及代码示例
- Elixir Kernel.then用法及代码示例
- Elixir Kernel.spawn用法及代码示例
- Elixir Kernel.defmodule用法及代码示例
- Elixir Kernel.SpecialForms.quote用法及代码示例
- Elixir Kernel.left > right用法及代码示例
- Elixir Kernel.binding用法及代码示例
注:本文由纯净天空筛选整理自elixir-lang.org大神的英文原创作品 Kernel.get_and_update_in(path, fun)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。