Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Passing in functions that throw exceptions

I have the following toy example

func identity<T>(a : T) -> T{
  return a
}

func applyIdentity<T>(f : T->T, t:T) -> T{
  return f(t)
}

applyIdentity(identity, t:1)

And this works without a hitch. However, once I try to throw an exception in identity like so:

enum MyError: ErrorType{
  case MyErrorFoo
};

func identity<T>(a : T) throws -> T{
  if (true) {
    return a
  } else {
    throw MyError.MyErrorFoo
  }
}
...

The type checker complains on the applyIdentity(identity, t:1) call with message:

Argument for generic parameter 'T' could not be inferred

Any idea why this may be happening?

like image 436
Kenta Labur Avatar asked Oct 06 '15 16:10

Kenta Labur


People also ask

How do you make a function throw an error in Swift?

To indicate that a function, method, or initializer can throw an error, you write the throws keyword in the function's declaration after its parameters. A function marked with throws is called a throwing function. If the function specifies a return type, you write the throws keyword before the return arrow ( -> ).

Can we pass function as a parameter in Swift?

Every function in Swift has a type, consisting of the function's parameter types and return type. You can use this type like any other type in Swift, which makes it easy to pass functions as parameters to other functions, and to return functions from functions.

What is Rethrows in Swift?

Rethrows in Swift allows forwarding a thrown error by a given function parameter. It's used a lot in methods like map , filter , and forEach and helps the compiler to determine whether or not a try prefix is needed.

What is difference between throw and throws in Swift?

The main difference between throw and throws is like "One declares it and the other one actually does it." throw keyword is used to throw exception explicitly from any method or static block while throws keyword is used in method declaration, denoted which exception can possible be thrown by this method.


1 Answers

Your (second) identity() method can throw an error, therefore it has the type T throws -> T, not T -> T.

If applyIdentity() should just forward an error thrown in f() to the caller then you can define it as

func applyIdentity<T>(f : T throws ->T , t:T) rethrows -> T {
    return try f(t)
}

See also "Declarations" in the Swift book:

Rethrowing Functions and Methods

A function or method can be declared with the rethrows keyword to indicate that it throws an error only if one of it’s function parameters throws an error. These functions and methods are known as rethrowing functions and rethrowing methods. Rethrowing functions and methods must have at least one throwing function parameter.

like image 51
Martin R Avatar answered Nov 15 '22 09:11

Martin R