为什么在Ecto查询中需要引脚操作符?

时间:2016-11-08 10:39:35

标签: elixir ecto

在Elixir中,引脚运算符用于防止变量重新绑定。但是,关于像

这样的Ecto查询
from u in User, where: u.username == ^username

编程Phoenix 状态的作者(在第7章中)

  

请记住,^运算符(称为pin运算符)意味着我们希望 ^ username 保持不变。

但这听起来不对,因为显然,查询中的比较不会导致任何重新绑定变量。

这本书的作者(JoséValim合着)是错误的吗? Ecto中的引脚运算符只是查询Ecto DSL的构造而不是通常的Elixir引脚运算符吗?或者,在宏扩展后,查询是否真的有机会重新绑定username

3 个答案:

答案 0 :(得分:24)

Ecto的查询依赖于宏来提供我们使用的强大的DSL。这意味着,无论from之后出现什么,都不是“常规”Elixir代码,而是最终将转换为SQL查询的DSL。因此,插入符号本身没有pin操作符,与模式匹配无关(尽管显然它仍然可以称为“pin操作符”,因为人们总是忘记插入符号&符号和星号)。这只是一个方便的操作员,Ecto的作者选择成为“插值算子”。如果没有它,你的示例中的username将按字面意思进行,并直接插入到生成的SQL中(尽管Ecto足够聪明,可以看到这不是你想要的,因此它会溢出错误。)

很棒的问题BTW,激励我阅读更多关于宏的信息(FP中的新手)。

答案 1 :(得分:19)

根据Ecto documentation,ecto中的pin运算符用于查询插值:

  

可以将外部值和Elixir表达式注入查询中   用^

表达
def with_minimum(age, height_ft) do
  from u in "users",
    where: u.age > ^age and u.height > ^(height_ft * 3.28),
    select: u.name
end

由于Ecto无法找出名为age的数据库函数或查询表达式,因此尝试跳过该引脚会出现错误:

  

(Ecto.Query.CompileError)变量age不是有效查询   表达。需要在查询中显式插入变量   用^

答案 2 :(得分:0)

如果要对现有变量的值进行模式匹配而不是重新绑定变量,则应使用引脚运算符^:

详细了解:http://elixir-lang.org/getting-started/pattern-matching.html

可以使用^将外部值和Elixir表达式注入到查询表达式中: 更多信息:https://hexdocs.pm/ecto/Ecto.Query.html