From "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.
A typical example is the map
method:
public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
If map
is called with a non-throwing transform, it does not throw
an error itself and can be called without try
:
// Example 1:
let a = [1, 2, 3]
func f1(n: Int) -> Int {
return n * n
}
let a1 = a.map(f1)
But if map
is called with a throwing closure then itself can throw
and must be called with try
:
// Example 2:
let a = [1, 2, 3]
enum CustomError: Error {
case illegalArgument
}
func f2(n: Int) throws -> Int {
guard n >= 0 else {
throw CustomError.illegalArgument
}
return n*n
}
do {
let a2 = try a.map(f2)
} catch {
// ...
}
- If
map
were declared as throws
instead of rethrows
then you would
have to call it with try
even in example 1,
which is "inconvenient" and bloats the code unnecessary.
- If
map
were declared without throws/rethrows
then you could not
call it with a throwing closure as in example 2.
The same is true for other methods from the Swift Standard Library
which take function parameters: filter()
, index(where:)
, forEach()
and many many more.
In your case,
func throwCustomError(function:(String) throws -> ()) throws
denotes a function which can throw an error, even if called with
a non-throwing argument, whereas
func rethrowCustomError(function:(String) throws -> ()) rethrows
denotes a function which throws an error only if called with a
throwing argument.
Roughly speaking, rethrows
is for functions which do not throw
errors "on their own", but only "forward" errors from their function
parameters.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…