@@ -35,48 +35,59 @@ import scala.annotation.nowarn
35
35
* which is expected to be more efficient than calling both `isDefinedAt`
36
36
* and `apply`.
37
37
*
38
- * The main distinction between `PartialFunction` and [[scala.Function1 ]] is
39
- * that the user of a `PartialFunction` may choose to do something different
40
- * with input that is declared to be outside its domain. For example:
38
+ * Note that `isDefinedAt` may itself throw an exception while evaluating pattern guards
39
+ * or other parts of the `PartialFunction`. The same caveat holds for `applyOrElse`.
41
40
*
42
41
* {{{
43
42
* val sample = 1 to 10
44
43
* def isEven(n: Int) = n % 2 == 0
44
+ *
45
45
* val eveningNews: PartialFunction[Int, String] = {
46
46
* case x if isEven(x) => s"\$x is even"
47
47
* }
48
48
*
49
- * // The method collect is described as "filter + map"
49
+ * // The method " collect" is described as "filter + map"
50
50
* // because it uses a PartialFunction to select elements
51
51
* // to which the function is applied.
52
52
* val evenNumbers = sample.collect(eveningNews)
53
53
*
54
+ * // It's more usual to write the PartialFunction as a block of case clauses
55
+ * // called an "anonymous pattern-matching function". Since the collect method
56
+ * // expects a PartialFunction, one is synthesized from the case clauses.
57
+ * def evenly = sample.collect { case x if isEven(x) => s"\$x is even" }
58
+ *
59
+ * // A method that takes a Function will get one, using the same syntax.
60
+ * // Note that all cases are supplied since Function has no `isDefinedAt`.
61
+ * def evened = sample.map { case odd if !isEven(odd) => odd + 1 case even => even }
62
+ * }}}
63
+ *
64
+ * The main distinction between `PartialFunction` and [[scala.Function1 ]] is
65
+ * that the client of a `PartialFunction` can perform an alternative computation
66
+ * with input that is reported to be outside the domain of the function.
67
+ *
68
+ * For example:
69
+ *
70
+ * {{{
54
71
* val oddlyEnough: PartialFunction[Int, String] = {
55
72
* case x if !isEven(x) => s"\$x is odd"
56
73
* }
57
74
*
58
75
* // The method orElse allows chaining another PartialFunction
59
76
* // to handle input outside the declared domain.
60
- * val numbers = sample.map(eveningNews orElse oddlyEnough)
77
+ * val numbers = sample.map(eveningNews. orElse( oddlyEnough) )
61
78
*
62
- * // same as
79
+ * // The same computation but with a function literal that calls applyOrElse
80
+ * // with oddlyEnough as fallback, which it can do because a PartialFunction is a Function.
63
81
* val numbers = sample.map(n => eveningNews.applyOrElse(n, oddlyEnough))
82
+ * }}}
64
83
*
65
- * val half: PartialFunction[Int, Int] = {
66
- * case x if isEven(x) => x / 2
67
- * }
68
- *
69
- * // Calculating the domain of a composition can be expensive.
70
- * val oddByHalf = half.andThen(oddlyEnough)
71
- *
72
- * // Invokes `half.apply` on even elements!
73
- * val oddBalls = sample.filter(oddByHalf.isDefinedAt)
74
- *
75
- * // Better than filter(oddByHalf.isDefinedAt).map(oddByHalf)
76
- * val oddBalls = sample.collect(oddByHalf)
84
+ * As a convenience, function literals can also be adapted into partial functions
85
+ * when needed. If the body of the function is a match expression, then the cases
86
+ * are used to synthesize the PartialFunction as already shown.
77
87
*
78
- * // Providing "default" values.
79
- * val oddsAndEnds = sample.map(n => oddByHalf.applyOrElse(n, (i: Int) => s"[\$i]"))
88
+ * {{{
89
+ * // The partial function isDefinedAt inputs resulting in the Success case.
90
+ * val inputs = List("1", "two", "3").collect(x => Try(x.toInt) match { case Success(i) => i })
80
91
* }}}
81
92
*
82
93
* @note Optional [[Function ]]s, [[PartialFunction ]]s and extractor objects
@@ -86,7 +97,7 @@ import scala.annotation.nowarn
86
97
* | :---: | --- | --- | --- |
87
98
* | from a [[PartialFunction ]] | [[Predef.identity ]] | [[lift ]] | [[Predef.identity ]] |
88
99
* | from optional [[Function ]] | [[Function1.UnliftOps#unlift ]] or [[Function.unlift ]] | [[Predef.identity ]] | [[Function1.UnliftOps#unlift ]] |
89
- * | from an extractor | `{ case extractor(x) => x }` | `extractor.unapply _ ` | [[Predef.identity ]] |
100
+ * | from an extractor | `{ case extractor(x) => x }` | `extractor.unapply(_) ` | [[Predef.identity ]] |
90
101
*
91
102
*
92
103
* @define applyOrElseOrElse Note that calling [[isDefinedAt ]] on the resulting partial function
0 commit comments