以下是我在Swift中可以做的事情:
extension Int {
func square() -> Int { return self * self }
}
然后像这样称呼它:3.square()
,它给了我9
。另外,我可以这样做:Int.square(3)
,它会给我() -> (Int)
。因此,Int.square(3)()
会9
。
但是,如果我写let array = [1, 2, 3]; Array.map(array)
,则会显示错误Cannot convert value of type 'Array<Int>' to expected argument of type '[_]'
问题是,我怎么能以这种方式使用Array.map?
修改 好的,我会尝试详细解释我的问题。现在,我的功能如下:
func map<T, U>(f: T -> U) -> [T] -> [U] {
return { ts in
ts.map(f)
}
}
它可以工作,但仅适用于数组。有许多类型都有map函数,并且为每种类型声明全局函数都不是很好。所以,让我们说C型有地图函数C<T> -> (T -> U) -> C<U>
另外,假设我有f
函数,将A -> B -> C
转换为B -> A -> C
。
所以,看起来我可以这样做:
let array = [1, 2, 3]
let square: Int -> Int = {$0 * $0}
map(square)(array) // [1, 4, 9], works fine
f(Array.map)(square)(array) // Error
问题不在于代码可读性,而在于Swift的类型系统是如何工作的。
答案 0 :(得分:2)
在带有square的示例中,编译器可以推断表达式的类型。换句话说:
let f = Int.square(3)
与
相同let f:() -> Int = Int.square(3)
但是,map是一个在闭包返回类型上参数化的泛型函数:
public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
因此,这会产生错误,因为编译器不知道T是什么:
let f = Array<Int>.map([1, 2, 3])
但是,您可以明确地告诉它T是这样的:
let f: ((Int) throws -> Int) throws -> [Int] = Array.map([1, 2, 3])
try! f({$0 * $0})
我认为这回答了关于方形和地图的第一个问题。我不完全理解你关于转换A - &gt;的其余问题。 B - &gt; C至B - &gt; A - &gt; C.也许你可以提供关于f的外观的更多信息。
答案 1 :(得分:2)
Array.map
函数定义为:
public func map<T>(self: [Self.Generator.Element]) -> (@noescape Self.Generator.Element throws -> T) rethrows -> [T]
这里的问题是编译器无法推断transform
函数或T
的返回类型。所以你必须通过以下两种方式来定义它:
// variable declaration
let mapping: (Int -> Int) throws -> [Int] = Array.map(array)
// or (especially useful for further function calls)
aFunction(Array.map(array) as (Int -> Int) throws -> [Int])
您还可以看到map
功能被标记为rethrows
,其被&#34;翻译&#34;如果您使用该功能,请throws
。 (它看起来像一个错误,但闭包没有rethrows
这可能是造成这种行为的原因。)
所以函数f
看起来像这样,以便与Array.map
一起使用:
// where
// A is the array
// B is the function
// C the type of the returned array
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> (A throws -> C) {
return { b in
{ a in
try f2(a)(b)
}
}
}
// or with a forced try! so you don't have to use try
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> A -> C {
return { b in
{ a in
try! f2(a)(b)
}
}
}
// call f (use try if you use the first implementation)
let square: Int -> Int = {$0 * $0}
f(Array.map)(square)