对大头针 (^) 运算符的使用感到困惑

Confusion over the use of the pin (^) operator

我正在查看一些如下所示的 Elixir 代码:

  @to_preload [
    :last_modified_by,
    change_request: [application: [:app_definition]],
    comments: [:user]
  ]

  def preload(query) do
    preload(query, ^@to_preload)
  end

我相信调用 preload(query, ^@to_preload) 实际上是对 Query.preload/3 宏的调用,因为该文件有一个 import Ecto.Query.

所以我的问题是,在那个调用中 ^ 在模块属性 @to_preload 前面到底做了什么?

你是对的。 preload里面指的是Ecto.Query.preload/3。来自 Ecto 的文档:

When writing a query, you are inside Ecto's query syntax. In order to access params values or invoke Elixir functions, you need to use the ^ operator, which is overloaded by Ecto

这就是使用 pin 运算符 (^) 的原因。你需要使用它,以便可以插值模块属性。

如果您在不使用 pin 运算符的情况下编写查询,则会出现以下错误:

** (Ecto.Query.CompileError) `@to_preload` is not a valid preload expression.
preload expects an atom, a list of atoms or a keyword list with more preloads as
values. Use ^ on the outermost preload to interpolate a value

因此,您分享的代码相当于:

def preload(query) do
  preload(query, [
    :last_modified_by,
    change_request: [application: [:app_definition]],
    comments: [:user]
  ])
end

实际上 an example in preload's documentation 使用了 pin 运算符。正在定义的函数也被称为 preload 可能会令人困惑。然而,由于数量的关系,没有混淆,因为 Ecto.Query 的预加载可以接受 2 或 3 个参数,而这里定义的只需要 1.