Reputation: 43
I'm experimenting usage of closurse for First Order Predicate calculus, and I intend to define the following function :
func ASSUM<U, V>(p: @escaping Pred<U>) -> (Pred<U>) -> Pred<(U, V)> {
return { q in AND1(p: p, q: q) }
}
that takes as parameter a predicate p: Pred<U>
, where Pred<U>
is a typealias for (T) -> Bool
:
typealias Pred<T> = (T) -> Bool
The return of ASSUM
is a Predicate transformer closure of type (Pred<U>)->Pred<(U,V)>
.
However the compiler return the following error :
Passing non-escaping parameter 'q' to function expecting an @escaping closure
I understand that the function AND1
as defined requests an escaping parameter :
func AND1<U, V>(p: @escaping Pred<U>, q: @escaping Pred<V>) -> Pred<(U, V)> {
return { (x, y) in (p(x) && q(y)) }
}
but I did not succeed in explicitly making q
in { q in AND1(p: p, q: q) }
escaping.
How can I fix this?
Upvotes: 2
Views: 1488
Reputation: 73176
You must explictly add the @escaping
attribute to the argument of the return type closure of ASSUM
:
typealias Pred<T> = (T)->Bool
func AND1<U, V>(p: @escaping Pred<U> , q: @escaping Pred<V>) -> Pred<(U, V)> {
return { (x,y) in (p(x) && q(y)) }
}
func ASSUM<U, V>(p: @escaping Pred<U>) -> (@escaping Pred<V>) -> Pred<(U, V)> {
/* ^ note: I believe you
want V here, not U */
return { AND1(p: p, q: $0) }
}
In the returned closure, q
(anonymous $0
argument) is correctly inferred as @escaping
(and needn't be explicitly marked as such, as pointed out by @Hamish, thanks!).
Note also that the generic type V
in ASSUM
must be inferred by explicit type annotation (or conversion) by the caller, as it is not included in any of the arguments to ASSUM
.
/* example usage */
let foo = { $0 < 2 }
let bar = { $0 != "bar" }
let fooAnd: (@escaping Pred<String>) -> Pred<(Int, String)> = ASSUM(p: foo)
let fooAndBar = fooAnd(bar)
print(fooAndBar((1, "foo"))) // true
print(fooAndBar((1, "bar"))) // false
print(fooAndBar((2, "foo"))) // false
Finally, ALLCAPITAL
function names is not in line with the Swift naming convention: you should prefer camelCase
naming instead (see e.g. the Swift API guidelines for additional details).
Upvotes: 1