的回答您的具體問題:
當你定義在朱莉婭一個新的類型,常見的是一些在Base
標準方法擴展到新的類型,包括deepcopy
。例如:
type MyType
x::Vector
y::Vector
end
import Base.deepcopy
Base.deepcopy(m::MyType) = MyType(deepcopy(m.x), deepcopy(m.y))
現在,您可以撥打deepcopy
超過MyType
一個實例,你會得到的MyType
一個新的,真正獨立,副本輸出。
請注意,我的import Base.deepcopy
實際上是多餘的,因爲我在我的函數定義中引用了Base
,例如, Base.deepcopy(m::MyType)
。但是,我做了這兩個向您展示了從Base
擴展方法的兩種方法。
其次注意,如果您的類型有很多領域,你可能反而比使用deepcopy
領域的迭代如下:
Base.deepcopy(m::MyType) = MyType([ deepcopy(getfield(m, k)) for k = 1:length(names(m)) ]...)
你的代碼中的註釋:
首先, Julia的標準做法是大寫類型名稱,例如Component1
而不是component1
。當然,你不必這樣做,但...
二,從Julia docs performance tips:聲明覆合類型的字段的具體類型。請注意,您可以參數化這些聲明,例如
type Component1{T1, T2}
x::T1
y::T2
end
第三,這裏是我會怎樣定義你的新類型:
type Mixture{T}
components::Vector{T}
Mixture{T}(c::Vector{T}) = new(c)
end
Mixture{T}(c::Vector{T}) = Mixture{eltype(c)}(c)
Mixture(x, K::Int) = Mixture([ deepcopy(x) for k = 1:K ])
有我的代碼和你之間這裏有幾個重要區別。我會一次一個地檢查他們。
您的K
字段是多餘的(我認爲),因爲它似乎只是components
的長度。所以它可能是簡單的length
方法只是擴展到新的類型,如下所示:
Base.length(m::Mixture) = length(m.components)
,現在你可以使用length(m)
,其中m
是得到什麼以前存儲在K
領域Mixture
一個實例。
您的類型mixture
中的內部構造函數不常見。標準做法是讓內部構造函數將一對一(依次)與您的類型的字段相對應的參數,然後內部構造函數的其餘部分僅執行任何錯誤檢查,只要您初始化類型。你偏離了這個,因爲qq
不是(必然)是一個數組。這種行爲更適合外部構造函數。那麼,我用構造函數做了什麼?
Mixture
的內部構造函數除了通過new
將參數傳遞給字段之外,沒有其他任何操作。這是因爲目前沒有任何錯誤檢查需要執行(但我可以在將來輕鬆添加一些錯誤)。
如果我想調用這個內部構造函數,我需要寫一些像m = Mixture{MyType}(x)
,其中x
是Vector{MyType}
。這有點煩人。因此,我的第一個外部構造函數使用eltype(x)
自動推斷{...}
的內容。因爲我的第一個外部構造的,我可以用現在初始化Mixture
的m = Mixture(x)
代替m = Mixture{MyType}(x)
我的第二個外部構造對應於你內心的構造函數。在我看來,您在此之後的行爲是在components
的每個字段中重複使用Mixture
,並重復使用K
次。所以我通過x
來完成循環理解,只要定義了deepcopy
方法就可以工作。如果不存在deepcopy
方法,則會出現No Method Exists
錯誤。這種編程稱爲鴨子打字,在Julia中,使用它通常沒有性能損失。
請注意,我的第二個外部構造函數會調用我的第一個外部構造函數K
次,並且每次我的第一個外部構造函數都會調用我的內部構造函數。在更復雜的情況下,以這種方式嵌套功能將大量減少代碼重複。
對不起,這是我知道的很多東西。希望能幫助到你。
謝謝您的完整回覆。我很熟悉多次調度的概念,但我不確定最好的方法是修改Base.deepcopy。 也感謝您的意見。關於第三條評論,並且避免了在構造函數中聲明類型的需要,儘管我設法使用了你的方法,但是我不太明白它! – Adham
@Adham我已經更新了我的答案。如果現在還不清楚,讓我知道,我會再試一次:-) –
謝謝。現在更清楚了(對我來說,作爲Julia的初學者:D) – Adham