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)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。
