在Elixir中,引脚运算符用于防止变量重新绑定。但是,关于像
这样的Ecto查询from u in User, where: u.username == ^username
编程Phoenix 状态的作者(在第7章中)
请记住,^运算符(称为pin运算符)意味着我们希望 ^ username 保持不变。
但这听起来不对,因为显然,查询中的比较不会导致任何重新绑定变量。
这本书的作者(JoséValim合着)是错误的吗? Ecto中的引脚运算符只是查询Ecto DSL的构造而不是通常的Elixir引脚运算符吗?或者,在宏扩展后,查询是否真的有机会重新绑定username
?
答案 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