2014-03-04 59 views
6

我在Elixir中編寫了一個簡單的例子,雖然它起作用,但我並不十分了解。elixir中的尾遞歸調用和默認參數

defmodule MyList do 
    def sum([],acc \\ 0), do: acc 
    def sum([head | tail], acc), do: sum(tail,acc + head) 
end 

當我打電話MyList.sum我得到預期的結果

sum([]) => 0 
sum([1,2,3]) => 6 

,因爲編譯器會引發錯誤

def sum/2 has default values and multiple clauses, use a separate clause for declaring defaults 

所以我不能在第二和添加默認PARAM我問題是,sum([1,2,3])是如何工作的?它不符合任何定義。 函數仍然是尾遞歸?

+0

我想知道這是尾遞歸還是不是我自己。我認爲它可能會成爲現實,因爲你不會強迫任何應該強制代碼創建棧幀的東西。 –

+0

它是尾遞歸的。我已經更新了回覆。 – sasajuric

回答

9

當你有一個可選參數multiclause,您可以指定默認的身體不太條款:

defmodule MyList do 
    def sum(list, acc \\ 0) # sets up default arguments 

    def sum([],acc), do: acc 
    def sum([head | tail], acc), do: sum(tail,acc + head) 
end 

關於你的榜樣,我只是猜測,但我認爲你的代碼量的東西如下:

defmodule MyList do 
    # implicitly generated due to default argument 
    def sum(list), do: sum(list, 0) 

    def sum([],acc), do: acc 
    def sum([head | tail], acc), do: sum(tail,acc + head) 
end 

這就是爲什麼sum([1,2,3])也適用。

編輯: 函數絕對是尾遞歸。如果函數做的最後一件事是另一個函數(或它本身)的調用,那麼它是一個尾部調用。所以在這種情況下,當我們調用sum(tail, acc + head)時,首先計算參數,然後發生尾遞歸調用。

+0

那麼,關於我的問題,是從第一個定義繼承到其餘的默認參數?它看起來像是發生了什麼,它可以解釋爲什麼定義無身體條款工作 – Batou99

+0

是的,默認參數是繼承(或者說是傳遞)。第二個片段解釋了這一點。該片段中的代碼與原始代碼相當。函數'sum/1'將調用'sum/2'作爲第二個參數發送0。所以每個'sum/2'子句都會收到這個默認值。 Body-less子句做同樣的事情,但它似乎更清晰,更清晰,因爲默認值從任何子句中取出,並在頂部單獨指定。 – sasajuric