为什么我不能链接String.replace?

Mar*_*var 31 elixir

我正在研究价格格式函数,它采用浮点数并正确表示.

恩.190.5,应该是190,50

这就是我提出的

  def format_price(price) do
    price
    |> to_string
    |> String.replace ".", ","
    |> String.replace ~r/,(\d)$/, ",\\1 0"
    |> String.replace " ", ""
  end
Run Code Online (Sandbox Code Playgroud)

如果我运行以下.

format_price(299.0)
# -> 299,0
Run Code Online (Sandbox Code Playgroud)

看起来它只是通过第一次更换.现在,如果我将此更改为以下内容.

  def format_price(price) do
    formatted = price
    |> to_string
    |> String.replace ".", ","

    formatted = formatted
    |> String.replace ~r/,(\d)$/, ",\\1 0"

    formatted = formatted
    |> String.replace " ", ""
  end
Run Code Online (Sandbox Code Playgroud)

然后一切似乎都很好.

format_price(299.0)
# -> 299,00
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

Gaz*_*ler 31

编辑在Elixir的主分支上,如果存在参数,编译器将警告函数是否在没有括号的情况下被管道输入.


这是一个优先级问题,可以使用显式括号修复:

price
|> to_string
|> String.replace(".", ",")
|> String.replace(~r/,(\d)$/, ",\\1 0")
|> String.replace(" ", "")
Run Code Online (Sandbox Code Playgroud)

因为函数调用的优先级高于|>运算符,所以代码与以下代码相同:

price
|> to_string
|> String.replace(".",
  ("," |> String.replace ~r/,(\d)$/,
    (",\\1 0" |> String.replace " ", "")))
Run Code Online (Sandbox Code Playgroud)

如果我们替换最后一个条款:

price
|> to_string
|> String.replace(".",
  ("," |> String.replace ~r/,(\d)$/, ".\\10"))
Run Code Online (Sandbox Code Playgroud)

然后再次:

price
|> to_string
|> String.replace(".", ",")
Run Code Online (Sandbox Code Playgroud)

应该解释为什么你得到那个结果.