Почему операторы буфера необходимы в запросах Ecto?

В Elixir оператор булавки используется для предотвращения перепроверки переменных. Однако в отношении запроса Ecto, такого как

from u in User, where: u.username == ^username

авторы состояния программирования Phoenix (в главе 7), что

Помните, что оператор ^ (называемый оператором вывода) означает, что мы хотим сохранить ^ имя пользователя.

Но это звучит не так, потому что, по-видимому, сравнение в запросе не должно вызывать перезаписи переменных.

Ошибочны ли авторы книги (которые соавтор Хосе Валим)? Является ли оператор булавки в Ecto запрашивает просто конструкцию Ecto DSL вместо обычного оператора вывода Elixir? Или запрос действительно получит возможность перестроить username после расширения макросов?

Ответы

Ответ 1

Ecto-запросы полагаются на макросы, чтобы обеспечить мощный DSL, который мы используем. Это означает, что все, что приходит после from, не является "обычным" кодом Elixir, а DSL, которое в конечном итоге преобразуется в SQL-запрос. Таким образом, каретка не является оператором буксировки как таковой, и не имеет никакого отношения к сопоставлению с образцом (хотя, очевидно, его все еще можно назвать оператором булавки, потому что люди всегда забывают слова, такие как каретка, амперсанд и звездочка). Это просто удобный оператор, который авторы Ecto предпочитают быть "оператором интерполяции". Без него username из вашего примера будет взято буквально и вставлено непосредственно в сгенерированный SQL (хотя Ecto достаточно умен, чтобы видеть, что это не то, что вы хотите, чтобы оно проливало ошибку).

Отличный вопрос BTW, вдохновил меня больше узнать о макросах (новичок в FP здесь).

Ответ 2

Согласно Документация по Ecto, оператор pin в ecto используется для интерполяции запросов:

Внешние значения и выражения Эликсира могут быть введены в запрос выражение с ^

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 не является допустимым запросом выражение. Переменные должны быть явно интерполированы в запросах с ^

Ответ 3

Оператор булавки ^ должен использоваться, если вы хотите сопоставить шаблон с существующим значением переменной, а не переупорядочивать переменную:

Дополнительная информация: http://elixir-lang.org/getting-started/pattern-matching.html

Внешние значения и выражения Elixir могут быть введены в выражение запроса с помощью: дальше: https://hexdocs.pm/ecto/Ecto.Query.html