As far as I understand, rethrows essentially creates two functions from a single declaration/definition, like so:
func f(_ c: () throws -> Void) rethrows { try c()}
// has the same effect as declaring two seperate functions, with the same name:
func g(_ c: () throws -> Void) throws { try c() }
func g(_ c: () -> Void) { c() }
If I have a rethrowing function, like f, is there way to save it as a closure in it's "non-throwing" form? Hypothetically, like so:
let x: (() -> Void) -> Void = f
// invalid conversion from throwing function of type '(() throws -> Void) throws -> ()' to non-throwing function type '(() -> Void) -> Void'
x{ print("test") } // "try" not necessary, because x can't throw
Until someone comes up with a better solution: Use a wrapper
func f(_ c: () throws -> Void) rethrows { try c() }
let x: (() -> Void) -> Void = { f($0) }
Related
I know that I should use #discardableResult. So I have the following code:
#discardableResult func someFunc() { ... }
Then I just call it:
someFunc()
But if I have and use a pointer to this method then it doesn't work again. For example:
let someFunc = self.someFunc
someFunc() //unused warning
Is it possible to avoid _=someFunc() in this case?
Unfortunately, discardableResult only applies to method/function declarations. What you can do is to wrap the value-returning function in a void-returning closure:
#discardableResult
func f() -> Int { return 1 }
// the type annotation here is important
let someFunc: () -> Void = { f() }
Alternatively, write a function that "erases" the return type of functions:
func discardResult<R>(_ f: #escaping () -> R) -> (() -> Void) {
{ _ = f() }
}
let someFunc = discardResult(f)
The downside is that you need to write an overload of this for each arity:
func discardResult<T, R>(_ f: #escaping (T) -> R) -> ((T) -> Void) {
{ x in _ = f(x) }
}
func discardResult<T, U, R>(_ f: #escaping (T, U) -> R) -> ((T, U) -> Void) {
{ x, y in _ = f(x, y) }
}
func discardResult<T, U, V, R>(_ f: #escaping (T, U, V) -> R) -> ((T, U, V) -> Void) {
{ x, y, z in _ = f(x, y, z) }
}
// and so on
I'm having difficulties with the following lines of code after updating to Swift 3:
private var functionHandlers = [(() -> Int) -> ()]()
private var myFunction: (() -> Int)?
func doRegister() {
functionHandlers.append { (f: (() -> Int)) in
myFunction = f
}
}
That gave me the compiler error: Assigning non-escaping parameter 'f' to an escaping closure
So then, I tried this:
func doRegister() {
functionHandlers.append { (f: #escaping (() -> Int)) in
myFunction = f
}
}
and this:
func doRegister() {
functionHandlers.append { (f: (#escaping () -> Int)) in
myFunction = f
}
}
which, in both cases, fixed my first error, but then gave me a new compiler error: Cannot convert value of type '(#escaping (() -> Int)) -> ()' to expected argument type '(() -> Int) -> ()'
So then I tried changing the type of functionHandlers as follows:
private var functionHandlers = [(#escaping (() -> Int)) -> ()]()
but that just resulted in a syntax error.
Can anyone explain to me why this is happening and what I can do to fix this?
Looks like a bug to me. For some reason, the compiler doesn't like the syntax:
private var functionHandlers = [(#escaping () -> Int) -> ()]()
but it does like:
private var functionHandlers : [(#escaping () -> Int) -> ()] = []
It's the same symptom, but I'm unsure it's the same cause as the compiler rejecting the [TypeA.TypeB]() syntax with nested types. Although like that problem, another way of solving it is by using a typealias:
typealias F = (#escaping () -> Int) -> ()
private var functionHandlers = [F]()
You can then implement doRegister() as you correctly tried to implement it as:
func doRegister() {
functionHandlers.append { (f: #escaping () -> Int) in
myFunction = f
}
}
Although you should certainly file a bug report over [(#escaping () -> Int) -> ()]() not compiling.
I am attempting to implement Church Numerals in Swift 3. Currently, I have:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
func churchToNum(f: ((Int) -> Int) -> (Int)-> Int) -> Int {
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
At this line in my function numToChurch:
return f(numToChurch(n: n - 1)(f)(x))
I keep getting a compile-time error that "Closure of non-escaping parameter 'f' may allow it to escape". As a quick-fix, I accepted the recommended changes to include #escaping:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
But even after making the changes, I keep getting told the same error and it recommends adding another #escaping after "f:". I understand that this has to do with marking function parameters as #escaping to tell the compiler that the parameters can be stored or captured for functional programming. But I don't understand why I keep getting this error.
Original non-escaping question resolved
Help with understanding church encoding in Swift cont:
func zero(_f: Int) -> (Int) -> Int {
return { (x: Int) -> Int in
return x
}
}
func one(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(x)
}
}
func two(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(f(x))
}
}
func succ(_ f: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
return { (f : #escaping ((Int) -> Int)) -> Int in
return { (x : Int) -> Int in
return f(n(f)(x))
}
}
}
func sum(m: #escaping ((Int) -> (Int) -> Int)) -> ((Int) -> (Int) -> Int) -> (Int) -> (Int) -> Int {
return { (n: #escaping ((Int) -> Int)) -> (Int) -> (Int) -> Int in
return { (f: Int) -> (Int) -> Int in
return { (x: Int) -> Int in
return m(f)(n(f)(x))
}
}
}
You're using currying for multi-parameter functions. That isn't a very natural way to express things in Swift and it's making things complicated. (Swift is not a functional programming language.)
As your linked article says, "All Church numerals are functions that take two parameters." So do that. Make it a two parameter function.
typealias Church = (_ f: ((Int) -> Int), _ x: Int) -> Int
This is a function that takes two parameters, a function and its argument.
Now you want to wrap the argument in the function N times:
// You could probably write this iteratively, but it is pretty elegant recursively
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { (_, n) in n } }
// Otherwise, recursively apply the function
return { (f, x) in
numToChurch(n - 1)(f, f(x))
}
}
And getting back is just applying the function:
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1}, 0)
}
Just building up on this, you can curry it (and I think I'm just saying what #kennytm has also answered). Currying is just slightly more complicated in Swift:
typealias Church = (#escaping (Int) -> Int) -> (Int) -> Int
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { _ in { n in n } } }
return { f in { x in
numToChurch(n - 1)(f)(f(x))
}
}
}
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1})(0)
}
There's a very reasonable question: "Why do I need #escaping in the second case, but not in the first?" The answer is that when you pass the function in a tuple, you've already escaped it (by storing it in another data structure), so you don't need to mark it #escaping again.
To your further questions, using a typealias dramatically simplifies this problem and helps you think through your types much more clearly.
So what are the parameters of zero? Nothing. It's a constant. So what should its signature be?
func zero() -> Church
How do we implement it? We apply f zero times
func zero() -> Church {
return { f in { x in
x
} }
}
One and two are nearly identical:
func one() -> Church {
return { f in { x in
f(x)
} }
}
func two() -> Church {
return { f in { x in
f(f(x))
} }
}
What is the signature of succ? It takes a Church and returns a Church:
func succ(_ n: #escaping Church) -> Church {
Because this is Swift, we need a little nudge by adding #escaping and _ to make things more natural. (Swift is not a functional language; it decomposes problems differently. Composing functions is not its natural state, so the over-abundence of syntax should not shock us.) How to implement? Apply one more f to n:
func succ(_ n: #escaping Church) -> Church {
return { f in { x in
let nValue = n(f)(x)
return f(nValue)
} }
}
And again, what is the nature of sum? Well, we're in a currying mood, so that means it's a function that takes a Church and returns a function that takes a Church and returns a Church.
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church
Again, a little extra syntax is needed because Swift. (And as above I've added an extra let binding just to make the pieces a little more clear.)
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in { x in
let nValue = n(f)(x)
return m(f)(nValue)
} } }
}
The deep lesson here is the power of the Church typealias. When you try to think of Church numbers as "functions that blah blah blah" you quickly get lost in the curry and syntax. Instead, abstract them to be "Church numbers" and just think about what every function should take and return. Remember that a Church number is always a function that takes an Int and returns an Int. It never grows or shrinks from that no matter how many times it's been nested.
It's worth taking this example in a couple of other directions because we can play out some deeper ideas of FP and also how Swift should really be written (which are not the same....)
First, writing Church numbers in pointed style is...inelegant. It just feels bad. Church numbers are defined in terms of functional composition, not application, so they should be written in a point-free style IMO. Basically, anywhere you see { f in { x in ...} }, that's just ugly and over-syntaxed. So we want functional composition. OK, we can dig into some experimental stdlib features and get that
infix operator ∘ : CompositionPrecedence
precedencegroup CompositionPrecedence {
associativity: left
higherThan: TernaryPrecedence
}
public func ∘<T, U, V>(g: #escaping (U) -> V, f: #escaping (T) -> U) -> ((T) -> V) {
return { g(f($0)) }
}
Now, what does that do for us?
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return zero() }
return { f in f ∘ numToChurch(n - 1)(f) }
}
func succ(_ n: #escaping Church) -> Church {
return { f in f ∘ n(f) }
}
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in
n(f) ∘ m(f)
} }
}
So we don't need to talk about x anymore. And we capture the essence of Church numbers much more powerfully, IMO. Summing them is equivalent to functional composition.
But all that said, IMO this is not great Swift. Swift wants structure and methods, not functions. It definitely doesn't want a top-level function called zero(). That's horrible Swift. So how do we implement Church numbers in Swift? By lifting into a type.
struct Church {
typealias F = (#escaping (Int) -> Int) -> (Int) -> Int
let applying: F
static let zero: Church = Church{ _ in { $0 } }
func successor() -> Church {
return Church{ f in f ∘ self.applying(f) }
}
static func + (lhs: Church, rhs: Church) -> Church {
return Church{ f in lhs.applying(f) ∘ rhs.applying(f) }
}
}
extension Church {
init(_ n: Int) {
if n <= 0 { self = .zero }
else { applying = { f in f ∘ Church(n - 1).applying(f) } }
}
}
extension Int {
init(_ church: Church) {
self = church.applying{ $0 + 1 }(0)
}
}
Int(Church(3) + Church(7).successor() + Church.zero) // 11
#escaping is part of the argument type, so you need to do it like:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~
Complete, working code:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~ ^~~~~~
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
// ^~~~~~~~~
if n == 0 {
return { x in x }
} else {
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
}
func churchToNum(f: (#escaping (Int) -> Int) -> (Int) -> Int) -> Int {
// ^~~~~~~~~
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
let church = numToChurch(n: 4)
let num = churchToNum(f: church)
Note:
Your return type of numToChurch is wrong even without the #escaping part. You are missing a -> Int.
I have added the base n == 0 case in numToChurch, otherwise it will be an infinite recursion.
Since the result of numToChurch has an escaping closure, the same annotation needs to be added to that of churchToNum as well.
Hello i have some func for pagination messages.
class func listMessages() -> (Int, Int, ([ChatItemProtocol]) -> Void) {
let service = MessageService()
func list(count: Int, offset: Int, comp:([ChatItemProtocol]) -> Void) {
let params : [String : AnyObject] = ["offset" : offset, "limit" : count]
service.listMessagesForRoom(params) { (messages) in
comp(messages.map({$0}))
}
}
return list
}
and i have some error :
Cannot convert return expression of type '(Int, offset: Int, comp: ([ChatItemProtocol]) -> Void) -> ()' to return type '(Int, Int, ([ChatItemProtocol]) -> Void)' (aka '(Int, Int, Array<ChatItemProtocol> -> ())')
listMessages(...) expects the following tuple return type
(Int, Int, ([ChatItemProtocol]) -> Void)
The function list(...), on the other hand, uses the above as argument but will implicitly also contain a Void (/empty tuple type ()) return type. I.e., the full signature for list(...) is
(Int, Int, ([ChatItemProtocol]) -> Void) -> ()
leading to a type mis-match when you attempt to return list as the return value of listMessages(...).
Without knowing the purpose of your code, it is difficult to give any concrete advice, but you could fix the above by modifying the return type of listMessages(...) to include also the () return type, in so matching the signature of list(...)
class func listMessages() -> ((Int, Int, ([ChatItemProtocol]) -> Void) -> ())
I'm having trouble with a type error that seems to be incorrect. The following code produces the error:
"Cannot invoke baz with argument list of type (f: (A) -> (), g: (String) -> ())" As indicated, the "incorrect" type is the exact type of baz, which is being called.
NB: I pulled out 'succeed' and 'fail' for type clarity, but the same thing happens when using the functions as closures.
class Foo<A> {
..
func baz(f: (A) -> (), g: (String) -> ()) {
.. do some stuff
}
func bar<A, B>(f: (A -> B)) -> Foo<B> {
func succeed(a: A) -> () {
.. do some stuff
}
func fail(s:String) -> () {
.. do some stuff
}
baz(f: succeed, g: fail)
.. do some stuff
}
}
Your generic parameter A declared for function bar overrides the generic type declared for class Foo, you need to remove it:
class Foo<A> {
func baz(f: (A) -> (), g: (String) -> ()) {}
func bar<B>(f: (A -> B)) -> Foo<B> {
func succeed(a: A) -> () {}
func fail(s:String) -> () {}
baz(succeed, g: fail)
return Foo<B>()
}
}
It's something about your A protocol. I changed and created new F so it could compile and it works in my playground:
protocol F {
}
class Foo<A> {
func baz(f: (F) -> (), g: (String) -> ()) {
}
func bar<A, B>(f: (A -> B)) -> Foo<B> {
func succeed(a:F) -> () {}
func fail(s:String) -> () {}
baz(succeed, g:fail)
return Foo<B>()
}
}