2017-01-10 102 views
2

爲什麼此代碼以這種方式工作?有沒有一種方法可以用這種方式使用bar完成我想要的? (我知道有替代品做模式相匹配的字符串)串聯匹配的字符串插值

# Elixir 1.3.4 
defmodule MyMod do 

    @foo "abc" 

    def concatenation_operator_with_interpolation do 
    bar = "abc" 

    "#{@foo}::" <> matchworks = "abc::xyz" 
    IO.puts matchworks # xzy 

    "#{bar}::" <> matchbroke = "abc::xyz" # cannot invoke remote function String.Chars.to_string/1 inside match 
    IO.puts matchbroke # never runs 
    end 

end 

MyMod.concatenation_operator_with_interpolation 
+0

必須與字符串插值有關。我可以用'「#{bar}」=「abc」'重現這一點。 –

+1

'bar =「abc」; size = byte_size(bar); <<^bar :: binary-size(size)>><> matchworks =「abc :: xyz」' – Dogbert

+0

是的,我想知道是否有什麼我可以做的插補工作。以上內容不太簡潔......你知道嗎? –

回答

6

簡短的回答:你需要存儲的bar的大小,然後做<<^bar::binary-size(size)>> <> matchworks = "abc::xyz"

iex(1)> bar = "abc" 
"abc" 
iex(2)> size = byte_size(bar) 
3 
iex(3)> <<^bar::binary-size(size)>> <> matchworks = "abc::xyz" 
"abc::xyz" 
iex(4)> matchworks 
"::xyz" 
iex(5)> <<^bar::binary-size(size)>> <> matchworks = "ab::xyz" 
** (MatchError) no match of right hand side value: "ab::xyz" 

龍答:二進制匹配涉及串聯的情況下,除LHS上最後一個以外的所有二進制文件必須是編譯時已知的常量值或具有明確的大小值。

在第一種情況下(它適用於你),Elixir在編譯時計算插值,因爲裏面的所有表達式都是編譯時間常量,並且用類似"abc" <> matchworks = "abc::xyz"的東西代替它,它工作正常。

在第二種情況下,bar是一個變量,因此"#{bar}"可以在運行時具有任何值,因此您需要明確指定大小。

+0

謝謝!你的描述爲什麼恆定的作品是非常有意義的。 –