鍍金池/ 問答/網(wǎng)絡安全/ Elixir模式匹配中匹配Range的疑惑

Elixir模式匹配中匹配Range的疑惑

我的疑惑在于這兩個函數(shù)中的Range匹配

我測試如下代碼是可以執(zhí)行的(分段查找):

defmodule Chop do
  def guess(actual, range = low..high) do
    guess = div(low+high, 2)
    IO.puts "Is it #{guess}?"
    _guess(actual, guess, range)
  end

  defp _guess(actual, actual, _),
    do: IO.puts "Yes, it's #{actual}"

  defp _guess(actual, guess, _low..high)
      when guess < actual,
    do: guess(actual, guess+1..high)

  defp _guess(actual, guess, low.._high)
      when guess > actual,
    do: guess(actual, low..guess-1)
end
Chop.guess(271, 1..1000)
"""
Is it 500?
Is it 250?
Is it 375?
Is it 312?
Is it 281?
Is it 265?
Is it 273?
Is it 269?
Is it 271?
Yes, it's 271
"""

不懂 _low..high 和 low.._high 是如何執(zhí)行匹配的,比如傳入?yún)^(qū)間 1..50,
匹配效果是不一樣的嗎?求解答,非常感謝?。

回答
編輯回答
巷尾

That's easy. 我給你翻譯下這段歌詞:

defmodule Chop do
  def guess(actual, range = low..high) do
    guess = div(low+high, 2)
    IO.puts "Is it #{guess}?"
    _guess(actual, guess, range)
  end
  
  defp _guess(actual, guess, low..high) do
      cond  do
      guess == actual         -> IO.puts "Yes, it's #{actual}"
      guess < actual -> guess(actual, guess+1..high)
      guess > actual -> guess(actual, low..guess-1)
     
    end
  end
end
Chop.guess(271, 1..1000)

這個程式在邏輯上是等價的, 雖然一個是條件語句, 一個是pattern matching.

其實

  defp _guess(actual, actual, _),
    do: IO.puts "Yes, it's #{actual}"

  defp _guess(actual, guess, _low..high)
      when guess < actual,
    do: guess(actual, guess+1..high)

  defp _guess(actual, guess, low.._high)
      when guess > actual,
    do: guess(actual, low..guess-1)

它就是一個pattern matching, 只是你需要意識到把guess > actual, guess > actual, 以及其它任意情況(在這裏就只剩下相等啦)是作爲match的條件而存在的.

你也可以自己改寫成另一種pattern matching, 即case guess do形式, 這兩者是完全等價的, 只是看自己的品味, 窩寫standard ml的時候更喜歡case哈.

可能你對pattern matching還不熟悉, 多寫寫就行啦, elixir的精華之一是pattern matching, 你以後可以儘可能的用patter matching, 有些時候會比較燒腦, 比起定義本地變量(典型的如sml中的let in)也可能會效率低些(因爲很多情況會以無法使用尾遞歸爲代價), 但是會非常簡潔, 非常具有美感, 好好發(fā)現(xiàn)elixir的美吧, 掃年, functional programming的大門在等著你打開

2018年1月2日 09:10