具有串联匹配的字符串插值

时间:2017-01-10 15:57:07

标签: elixir

为什么这段代码会这样运作?有没有办法以这种方式用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

1 个答案:

答案 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}"在运行时可以有任何值,因此您需要明确指定大小。