我想要做這樣的事情:是否可以將Int.init傳遞給Swift中的函數?
var x = ["10","20",30"]
var y = x.map(Int.init)
,但我得到這個錯誤
曖昧參考成員 '的init()'
我知道我可以只寫
var y = x.map { Int($0) }
但我想知道是否有其他方式。
我想要做這樣的事情:是否可以將Int.init傳遞給Swift中的函數?
var x = ["10","20",30"]
var y = x.map(Int.init)
,但我得到這個錯誤
曖昧參考成員 '的init()'
我知道我可以只寫
var y = x.map { Int($0) }
但我想知道是否有其他方式。
問題是,不存在Int
初始化程序,它只有 a String
參數。
init?(_ text: String, radix: Int = default)
雖然參數有一個默認值,這僅僅是在初始化器的調用點「填充」爲您編譯器。
當獲取對函數本身的引用時,默認參數值不會部分應用,也不會爲默認參數值的所有可能組合生成額外的重載。後者不僅會使代碼顯着膨脹,而且這兩個選項都會打破取決於在呼叫站點插入的默認參數值(例如#file
& #line
)。
爲了使其正常工作,函數值本身必須支持默認參數值,這會帶來相當多的複雜性。雖然它可能是未來版本的語言支持的東西。
一個簡單的解決方案,以得到你想要的行爲是隻寫上Int
的擴展,它增加了一個init(_:)
初始化器是再轉發到init(_:radix:)
:
extension Int {
/// Creates a new integer value from the given base-10 integer string, returning nil
/// if the string is in an invalid format.
init?(_ string: String) {
// we're saying (_:radix:) in order to disambiguate the call, the compiler
// will insert the default parameter value of radix: for us.
self.init(_:radix:)(string)
}
}
注意,在斯威夫特4,這可能是一個擴展FixedWidthInteger
,它爲標準庫的整數類型提供了init(_:radix:)
的實現。
現在,你可以說:
let x = ["10", "20", "30"]
let y = x.map(Int.init) // [Optional(10), Optional(20), Optional(30)]
爲Int.init
現在指的是我們的擴展初始化器。
而且這也適用同樣出色flatMap(_:)
:
let y = x.flatMap(Int.init) // [10, 20, 30]
這也將過濾掉從改造nil
元素(即不轉換爲整數的字符串)。
不錯!但是'y'仍然返回'[Int?]',可能不需要_optional_Ints。然後你可以在擴展中使用這個init結合'flatMap'來代替map' – Sajjon
@Sajjon Yup,剛剛在添加的過程中,當你評論:)不清楚哪兩個OP想要,但想了想提到它並沒有什麼壞處。 – Hamish
不錯! @ b-roy-dawson,你也可以使用這個解決方案,並把它擴展到[String]。像這樣:'擴展數組其中元素==字符串{整數:[Int] { return flatMap(Int.init) } }'with * usage:*'var y = x.integers' – Sajjon
問題歸結爲不能將具有默認參數的函數(如Int.init(_ text: String, radix: Int = default)
)分配到只有在「默認」參數「不存在」時才能「適合」的地方。
當你自己關閉,{ Int($0) }
,你告訴編譯器你想要默認值radix
適用。這不幸的是,這並不是隱含的。
您能詳細說明一下您的需求嗎? – Sajjon
[在map()中使用init()]的可能重複(https://stackoverflow.com/questions/33906791/using-init-in-map)。 –
@MartinR很好找。有趣的是編譯器不能消除初始化器的歧義。有時候你會很幸運,像'[false,true] .map(!)'這樣的東西可以工作。 – JAL