當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


Elixir Kernel.get_and_update_in用法及代碼示例

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 中的 key bar ;如果 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-lang.org大神的英文原創作品 Kernel.get_and_update_in(path, fun)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。