Generic map function will not accept valid closure [duplicate] - swift

This question already has an answer here:
What is the cause of this type error?
(1 answer)
Closed 6 years ago.
I have the following code in a 'SquareMatrix <T: HasZeroOne>' class whose data 'data' is stored in a [[T]] double array. I made this mapping function to mimic the standard Swift one.
public func map<S: HasZeroOne>(transform: (T) -> S) -> SquareMatrix<S> {
return SquareMatrix(data: data.map{(row: [T]) in row.map({(col: T) in transform(col)})})!
}
At first I tried the simpler syntax:
public func map<S: HasZeroOne>(transform: (T) -> S) -> SquareMatrix<S> {
return SquareMatrix(data: data.map{$0.map(transform)})!
}
But got the following error in both cases:
Cannot convert value of type '(T) -> S' to expected argument type '(_) -> _'
I'm completely lost. What have I done wrong?

As is always the way, I got an answer 5 minutes later. Not that the error message helped at all. The following works:
public func map<S: HasZeroOne>(transform: (T) -> S) -> SquareMatrix<S> {
return SquareMatrix<S>(data: data.map{$0.map(transform)})!
}
Note the <S>.
Hope someone finds this a useful hint!

Related

Is it possible to use Variadic Parameters within Closures?

Refurbished Question
Swift: Combining the use of Variadic Parameters with Closures
Is it possible to make a closure using variadic parameters?
func this(_ hello: (Int...) -> ()) {}
func that(_ yeah: Int...) {}
Here's what works: this(that)
Here's what didn't work:
this { foo in }, this { _ in }, this { }
I'm getting this error:
Cannot convert value of type '(_) -> ()' to expected argument type '(Int...) -> ()'
I even went so far as to change all Int... to Void...
I'm got the same results
With the additional warning of
When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? Replace '(Void...)' with '()' However, replacing Void... with ()... did the trick
Simplified Problem
let _: (()...) -> () = { _ in }
Causes this error:
Cannot convert value of type '(_) -> ()' to specified type '(()...) -> ()'
Is it possible to work around this?
You need to include the type in the closure:
this { (foo: Int...) in }
The type-inference engine isn't quite powerful enough to figure out this case. I suspect it's related to SR-6030.

RxSwift generic `Cannot convert value of type '(_) -> [Any]' to expected argument type '(String) -> _'`

I want to create an extension of ObservableType, but the following code doesn't compile.
public extension ObservableType {
public func foo<C: Collection>(_ calls: #escaping (E) -> C) -> Observable<[Any]> where C.Iterator.Element: ObservableType {
return flatMap { input in Observable.zip(calls(input)) { objects in objects }
}
}
}
// compile error
Observable.just("foo")
.foo { foo in
[Observable.just(User()), Observable.just(Repo())]
}
It throws an error: Cannot convert value of type '(_) -> [Any]' to expected argument type '(String) -> _'
I have no idea where the problem is. Thanks in advance
Your problem is that you return an array of two different types - User and Repo. If you change the return value to this one, for instance:
return [Observable.just(User()), Observable.just(User())] - it will work as expected.
Updated: In your case you can achive it so:
[Observable<Any>.just(User()), Observable<Any>.just(Repo())]
Updated: More correct to use the following return type for foo function - Observable<[C.Element.E]> IMHO.

"ambiguous use" on generic method after migration to swift 4

I am trying to migrate my code from xcode 8.2 swift 3.0.2 to xcode 9 swift 4, and I have problem with this code:
func test<T0, TRet>(_ fn: (T0) -> TRet) -> Void {
print("foo1")
print(T0.self)
}
func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
print("foo2")
print(T0.self)
print(T1.self)
}
let fn2 : (Int, Int) -> Int = { (x:Int, y:Int)->Int in
return x+y
}
test(fn2)
xcode 8.0.2, swift 3.0.2 results with:
foo2
Int
Int
xcode 9, swift 4 results with:
Playground execution failed:
error: MyPlayground.playground:12:1: error: ambiguous use of 'test'
test(fn2)
^
MyPlayground.playground:1:6: note: found this candidate
func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
^
Am I missing something? Is there any new feature in swift 4 that causes this error?
Update
I filed a bug at bugs.swift.org as suggested in the comments.
https://bugs.swift.org/browse/SR-6108
I ran into the same problem, and stumbled across a workaround that is (for my purposes) nicer than disambiguating via naming. Perhaps it is not even a workaround, just the way things have to be. It's also possible that this is newly-possible in Swift 4.1 (not sure, since I migrated directly from Swift 3 to 4.1)
Change this:
func test<T0, TRet>( fn: (T0) -> TRet) -> Void
...to this...
func test<T0, TRet>( fn: ((T0)) -> TRet) -> Void
(note the extra pair of parens around the T0 callback parameter, which explicitly makes it into a tuple-of-1)
After this change, test(fn2) compiles and calls the test<T0,T1,TRet> overload.
It seems that the compiler is able to treat a function with N arguments as a function with one N-way-tuple argument. Hence, both the (T0) -> TRet and (T0,T1) -> TRet overloads are candidates for fn2, and the call is ambiguous. Adding 2nd pair of parens ((T0)) -> TRet limits that overload to an argument with a single parameter or 1-way tuple.

Swift generic function with clousure

I've the following generic function (not part of any class):
func execFuncWithGenericParameter<T, U>(f: (T) -> U){
print(f("Hello World"))
}
I'd like to call this function in with a closure like this:
execFuncWithGenericParameter(f: { (p: String) -> Int in
print(p)
return 4711
})
But the compiler (iPad Swift Playground) tells me that "(String) -> U is not convertible to (T) -> U".
Naturelly I've done done some investigation and was the opinion that the Compiler automatically will infer the types.
Thanks.
The types are being inferred as far as the nature of f: (T) -> U is concerned. The problem is the call to f inside your first method.
Ask yourself: what if T were not String? Then f("Hello world") would be illegal. That is the quandary you've left the compiler with — and it rightly refuses to deal with it.
Here's a legal version:
func execFuncWithGenericParameter<T,U>(f: ((T) -> U), param:T){
f(param)
}
execFuncWithGenericParameter(f: { (p: String) -> Int in
print(p)
return 4711
}, param:"Hello")
Now the first method knows that param will be a T, so all is well. And in the second method, when we call the first method, T is String and param is a String, so it compiles (and runs, and prints).

Swift - Strange method signature syntax

I am unable to understand the following method signature I went through lastly while working on an open source framework:
public func myFunc<A: TypeOfA, B: TypeOfB, C: TypeOfC>
(someA: A)
-> (someB: B)
-> ReturnedType {
// BODY OF THE FUNC
}
Why is there 2 return arrows '->'? Does anyone know where I could get more info about this syntax? Did find anything in the Apple Swift doc.
I am NOT talking about the generics but about the way the parameters are declared.
And yes this compiles fine with xcode 7.3
Thanks
The function takes one argument, someA: A, and returns another function.
The function it returns takes someB: B and returns ReturnedType.
This is equivalent to:
public func myFunc<...>(someA: A) -> ((someB: B) -> ReturnedType) {
...
}
or
typealias SecondFunction = (someB: B) -> ReturnedType
public func myFunc<...>(someA: A) -> SecondFunction {
...
}