2016-06-07 36 views
7

我正在考慮寫一個類似於NamedArraysImages中定義的類型。比方說,我只是想要一個帶有一段元數據的數組,例如,當我將數組寫入磁盤時,我將在文件的頂部寫入一個用戶友好的名稱。 (這個細節是不相關的,我只是contriving一個例子。)如何避免使用新類型的Julia中的大量樣板文件?

所以我可能會做

type MyNamedArray 
    data::Array 
    name::ASCIIString 
end 

function mywrite(f,x::MyNamedArray) 
    write(f,x.name) 
    write(f,x.data) 
end 

什麼的,需要從基礎陣列不同的行爲沒有其他行爲。

在我的腦海中,「顯而易見」的是,我只希望在數組上運行的每個現有函數都可以在此類型的data字段上運行。在另一種語言例如Java我可能只是子類Array,並將name作爲實例字段添加到子類中,這會自動保留與所有現有Array操作的兼容性。但是,在朱莉婭,如果我嘗試一種如上所述的解決方案,我現在需要定義更多的功能,例如,就像@TimHoly和'davidavdav'在鏈接包中完成的一樣。

當然,我知道被迫用手寫出一些這些功能對於實現你沒有想過的事情很有用。例如。在上面給出的示例MyNamedArray中,可以通過指出我沒有定義名稱x::MyNamedArray * y::MyNamedArray來反對。但是如果我只是不關心這一點,並且希望代碼「可以正常工作」,而沒有太多的樣板文件呢? (請參閱循環遍歷符號以推送新方法定義in NamedArrays並手動編寫一百行定義in Images。絕大多數定義是樣板/「明顯」定義。)

特別要繼續我引用的示例,對於MyNamedArray,默認可能是x*y不再是MyNamedArray,也就是說,因爲每個函數都默認爲在底層數據上應用相同函數的「繼承」行爲,所以我們可以忽略所有預先存在函數的元數據。

注意,我發現Tomas Lycken的回答​​有洞察力,所以問題和答案here

我可以想到的最好的綜合方法是「你只需要把它吸起來寫出函數,或者編寫一個可以爲你做的宏。」如果是這樣的話,就這樣吧;我只是想知道如果我錯過了一個更好的選擇,特別是更好的方法來設計解決方案,使其更多朱利安和避免樣板。

回答

5

通過簡單描述子類別AbstractArrayhttp://docs.julialang.org/en/latest/manual/interfaces/#abstract-arrays,您可以獲得大部分途徑。實際上,您可以做得更好,並且子類DenseArray,此外還需要定義stride(可能是pointer)函數...允許您的自定義陣列與BLAS一起使用。這只是你需要定義的一些方法。這不是100%,因爲許多作者仍然傾向於過分限制只接受Array的方法,因爲他們可以輕鬆接受所有AbstractArrays。這在過去兩年得到了顯着改善,並且仍在不斷改善。

通常,我發現這裏非常有用的模式是根據抽象超類定義接口並儘可能地放鬆方法簽名。如果發送限制不是必需的,你可以允許任何類型,只需要輸入鴨子。如果您只是在告訴Julia它應該嘎嘎聲還是依賴其內部實現時纔將調度限制爲特定的葉類型,那麼您的工作變得更具可擴展性和可重用性。

+0

這裏有很多很好的建議;我會修補一下並回報。謝謝! – Philip

+0

我認爲這會引發一個關於實現接口和子類型之間邏輯關係的相關問題。在其他具有明確界面的語言中,這種區別對我來說已經很清楚了在朱莉婭這只是一個「調度與運行時間」的區別?換句話說,如果你將一個類型聲明爲一個超類型的子類型,那麼超類型上定義的方法也將在子類型上分派(假設你沒有覆蓋它們)。但是如果你還沒有實現非正式接口,那麼這些方法的實現可能會在運行時失敗? – Philip

+0

是的,這是[鴨打字](http://stackoverflow.com/questions/4205130/what-is-duck-typing)。它只是將錯誤向下移動一級 - 而不是爲sum(:: MyNamedArray)拋出一個MethodError,當它試圖在sum的實現中迭代或索引你的數組時,你會得到一個MethodError。這是一種運行時缺失的方法錯誤。 –

相關問題