@@ -707,7 +707,8 @@ can be values of any type that conforms to the `Error` protocol.
707
707
This approach matches the reality that
708
708
you don't know ahead of time every error that could happen
709
709
while the code is running,
710
- especially when propagating errors thrown by code you didn't write.
710
+ especially when propagating errors thrown somewhere else.
711
+ This approach also reflects the fact that errors can change over time.
711
712
New versions of a library can throw new errors ---
712
713
including libraries used by your dependencies ---
713
714
and the rich complexity of real-world user configurations
@@ -716,21 +717,48 @@ The error handling code in the examples above
716
717
always includes a default case to handle errors
717
718
that don't have their own specific ` catch ` clause.
718
719
719
- However,
720
- some code throws error of only a specific type,
721
- so it's useful to specify that type.
720
+ In some special cases,
721
+ you might write code that's specific about what error it throws:
722
722
723
- - When you encapsulate errors within some unit of code,
724
- like a library,
725
- if using a specific error type is useful for you.
726
- In this case,
727
- the library always handles all of its own errors.
728
- This kind of error is an implementation detail of the library.
729
-
730
- - When targeting an embedded system
723
+ - When running code on an embedded system
731
724
where dynamic allocation of memory isn't possible.
732
- Swift needs to allocate memory at run time
733
- when throwing an instance ` any Error ` or other boxed protocol types.
725
+ Throwing an instance ` any Error ` or another boxed protocol type
726
+ requires allocating memory at run time to store the error.
727
+ Throwing an error of a specific type instead
728
+ lets Swift allocate that memory upfront.
729
+
730
+ - When the errors are an implementation detail of a library,
731
+ or some other unit of code,
732
+ and aren't part of the interface to that code.
733
+ Because only the library's code throws errors ---
734
+ it doesn't propagate errors from other code ---
735
+ you can make an exhaustive list of all possible failures.
736
+ And because the library always handles its own errors,
737
+
738
+
739
+ Because all of these errors are thrown within the library's code,
740
+ and they're always handled within that library.
741
+ Because
742
+ Because the library's clients never see the errors,
743
+ ◊ the API surface expressively limitations don't matter
744
+
745
+ -
746
+ * In code that only rethrows errors,
747
+ especially when the throwing code comes from a closure the caller provided.
748
+ (However, neither rethrows nor typed throws is a strict superset of the other.)
749
+ Example: ` map ` in the stdlib.
750
+ Xref to reference section -- this chapter doesn't discuss rethrows
751
+
752
+
753
+ In most code,
754
+ you don't specify the type for the errors it throws,
755
+ implicitly throwing an error of type ` any Error `
756
+ However,
757
+ Swift also supports
758
+ some code only throws errors of a specific type.
759
+ in some places your code only throws
760
+ you might need to write code that throws errors of only a specific type,
761
+ so it's useful to specify that type.
734
762
735
763
- When you throw errors from code that
736
764
doesn't depend on any other throwing code,
@@ -754,9 +782,10 @@ enum StatisticsError: Error {
754
782
```
755
783
756
784
To specify that a function throws only ` StatisticsError `
757
- you write ` throws(StatisticsError) ` when declaring the function.
758
- Because you write a type after ` throws `
759
- this syntax is also called * typed throws* .
785
+ you write ` throws(StatisticsError) ` when declaring the function,
786
+ instead of just writing ` throws ` .
787
+ This syntax is also called * typed throws*
788
+ because you write the error type after ` throws ` --- for example:
760
789
761
790
``` swift
762
791
func summarize (_ ratings : [Int ]) throws (StatisticsError) {
@@ -768,69 +797,82 @@ func summarize(_ ratings: [Int]) throws(StatisticsError) {
768
797
counts[rating]! += 1
769
798
}
770
799
771
- print (" One star:" , counts[1 ]! )
772
- print (" Two stars:" , counts[2 ]! )
773
- print (" Three stars:" , counts[3 ]! )
774
-
775
800
print (" *" , counts[1 ]! , " -- **" , counts[2 ]! , " -- ***" , counts[3 ]! )
776
801
}
777
802
```
778
803
779
- <!-- XXX pick one flavor of summary above -->
804
+ In the code above,
805
+ the ` summarize(_:) ` function summarizes a list of ratings
806
+ expressed on a scale of 1 to 3.
807
+ This function throws an instance of ` StatisticsError ` if the input isn't valid.
808
+
809
+ You can use the shorthand notation ` throw .noRatings `
810
+ instead of writing ` throw StatisticsError.noRatings `
811
+ because the function's error type is already defined.
812
+
813
+
814
+ ◊ throws(StatisticsError) is a subtype of throws(any Error)
815
+ ◊ so you can write ` try summarize(...) ` in a plain ` throwing ` context too
816
+ - Most code that throws errors just writes ` throws ` .
817
+ This is the same as writing ` throws(any Error) ` .
818
+ However, you can write ` throws(SomeErrorType) `
819
+ to throw errors of a specific concrete type.
820
+
780
821
781
- When you write a specific error type,
782
- Swift checks at compile time that you don't throw any other errors.
783
822
823
+ When you write a specific error type,
824
+ Swift checks that you don't throw any other errors.
825
+ For example,
826
+ if you tried to use ` VendingMachineError ` from examples earlier in this chapter
827
+ in the ` summarize(_:) ` function above,
828
+ that code would produce an error at compile time.
784
829
830
+ ◊ rewrite
785
831
Code that throws a single specific error type
786
- doesn't include the default ` catch ` clause ---
832
+ doesn't need to include the default ` catch ` clause ---
787
833
instead, Swift verifies that every possible error value
788
834
has a corresponding ` catch ` clause.
789
835
836
+
837
+
838
+
839
+ In addition to specifying the error type for a function,
840
+ you can also write a specific error type
841
+ in a ` do ` -` catch ` block.
842
+ For example:
843
+
790
844
``` swift
791
- func printSummary (_ ratings : [Int ]) {
792
- do throws (StatisticsError) {
793
- try summarize (ratings)
794
- } catch {
795
- switch error {
796
- case .noRatings :
797
- print (" No ratings available" )
798
- case .invalidRating (let rating):
799
- print (" Invalid rating: \( rating ) " )
800
- }
845
+ let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
846
+ do throws (StatisticsError) {
847
+ try summarize (ratings)
848
+ } catch {
849
+ switch error {
850
+ case .noRatings :
851
+ print (" No ratings available" )
852
+ case .invalidRating (let rating):
853
+ print (" Invalid rating: \( rating ) " )
801
854
}
802
855
}
856
+ // Prints XXX
803
857
```
804
858
805
- ## XXX OUTLINE XXX
859
+ In this code, XXX
806
860
807
- - Most code that throws errors just writes ` throws ` .
808
- This is the same as writing ` throws(any Error) ` .
809
- However, you can write ` throws(SomeErrorType) `
810
- to throw errors of a specific concrete type.
811
861
812
- - In contrast, a concrete error type is useful in some special circumstances:
862
+ XXX
863
+ If a function or ` do ` block throws only errors of a single type,
864
+ the compiler infers that as the concrete error type.
865
+ You can explicitly write ` throws(any Error) ` to suppress that.
813
866
814
- * In code that only rethrows errors,
815
- especially when the throwing code comes from a closure the caller provided.
816
- (However, neither rethrows nor typed throws is a strict superset of the other.)
817
- Example: ` map ` in the stdlib.
818
- Xref to reference section -- this chapter doesn't discuss rethrows
867
+
868
+ ## XXX OUTLINE XXX
819
869
820
870
- You can also use opaque types like ` throws(some MyErrorProtocol) ` --
821
871
this is still "concrete" in sense that
822
872
the errors are all instances of the concrete type
823
873
that's hidden behind the opaque type.
824
874
And there's still one specific error type.
825
875
826
- - To specify the error type for a ` do ` block or a throwing function,
827
- write ` throws(E) ` where ` E ` is an error type.
828
- For example -- insert ` summarize ` from RUNNING EXAMPLE below.
829
-
830
- - If a function or ` do ` block throws only errors of a single type,
831
- the compiler infers that as the concrete error type.
832
- You can explicitly write ` throws(any Error) ` to suppress that.
833
-
834
876
- For a normal error (of boxed protocol type)
835
877
the ` catch ` clause needs to either include a general catch/default
836
878
that handles errors whose types the other clauses don't handle,
@@ -839,14 +881,6 @@ func printSummary(_ ratings: [Int]) {
839
881
without a default clause
840
882
by handling just that specific error type.
841
883
842
- XXX RUNNING EXAMPLE XXX
843
-
844
- ``` swift
845
- printSummary ([1 , 2 , 3 , 2 , 2 , 1 ])
846
- printSummary ([])
847
- printSummary ([1 , 100 ])
848
- ```
849
-
850
884
## Specifying Cleanup Actions
851
885
852
886
You use a ` defer ` statement to execute a set of statements
0 commit comments