2016-11-08 75 views
15

在Elixir中,pin操作符用於防止變量重新綁定。然而,對於一個外生查詢像爲什麼在Ecto查詢中需要pin操作符?

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

編程鳳凰狀態(第7章),其

記住,^運算符的作者(稱爲銷運營商)意味着我們想要保持^用戶名相同。

但是這聽起來並不正確,因爲很明顯,查詢中的比較不會導致變量重新綁定。

這本書的作者(JoséValim合着)是否寫錯了? Ecto中的pin操作符是否僅查詢Ecto DSL的構造,而不是通常的Elixir pin操作符?或者在宏展開之後,查詢是否真的有機會重新綁定username

閱讀更多:當你想要模式匹配對現有變量的值,而不是重新綁定變量

回答

12

根據Ecto documentation,在胞外銷運算符用於查詢插補:

外部值和藥劑表達式可以被注入到一個查詢 表達^

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 

試圖跳過引腳將給出錯誤的外生水溼找出一個數據庫函數或查詢命名age表達:可變age

(Ecto.Query.CompileError)是不是有效的查詢 表達。變量需要在查詢中明確插入 with^

16

Ecto的查詢依賴於宏來提供我們使用的強大的DSL。這意味着,不管是在from之後,不是「常規」Elixir代碼,而是最終將被轉換爲SQL查詢的DSL。因此,插入符號本身並不是pin操作符,並且與模式匹配無關(儘管顯然它仍然可以稱爲「pin操作符」,因爲人們總是忘記諸如符號符號星號 )。這是Ecto的作者選擇成爲「插值算子」的便利運營商。沒有它,你的例子中的username將從字面上被採取,並直接插入到生成的SQL(雖然Ecto足夠聰明,看到這不是你想要的,所以它泄漏了一個錯誤)。

偉大的問題順便說一句,啓發我閱讀更多關於宏(在FP這裏的新手)。

相關問題