Skip to content

Commit 60ec858

Browse files
authored
Merge pull request scala/scala#11041 from som-snytt/doc/pf
Tweak partial function doc
2 parents 7c2e8f8 + 0edc7fd commit 60ec858

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

library/src/scala/Option.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ object Option {
9999
* - [[toList]] — Unary list of optional value, otherwise the empty list
100100
*
101101
* A less-idiomatic way to use $option values is via pattern matching: {{{
102-
* val nameMaybe = request getParameter "name"
102+
* val nameMaybe = request.getParameter("name")
103103
* nameMaybe match {
104104
* case Some(name) =>
105105
* println(name.trim.toUppercase)

library/src/scala/PartialFunction.scala

+32-21
Original file line numberDiff line numberDiff line change
@@ -35,48 +35,59 @@ import scala.annotation.nowarn
3535
* which is expected to be more efficient than calling both `isDefinedAt`
3636
* and `apply`.
3737
*
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`.
4140
*
4241
* {{{
4342
* val sample = 1 to 10
4443
* def isEven(n: Int) = n % 2 == 0
44+
*
4545
* val eveningNews: PartialFunction[Int, String] = {
4646
* case x if isEven(x) => s"\$x is even"
4747
* }
4848
*
49-
* // The method collect is described as "filter + map"
49+
* // The method "collect" is described as "filter + map"
5050
* // because it uses a PartialFunction to select elements
5151
* // to which the function is applied.
5252
* val evenNumbers = sample.collect(eveningNews)
5353
*
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+
* {{{
5471
* val oddlyEnough: PartialFunction[Int, String] = {
5572
* case x if !isEven(x) => s"\$x is odd"
5673
* }
5774
*
5875
* // The method orElse allows chaining another PartialFunction
5976
* // to handle input outside the declared domain.
60-
* val numbers = sample.map(eveningNews orElse oddlyEnough)
77+
* val numbers = sample.map(eveningNews.orElse(oddlyEnough))
6178
*
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.
6381
* val numbers = sample.map(n => eveningNews.applyOrElse(n, oddlyEnough))
82+
* }}}
6483
*
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.
7787
*
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 })
8091
* }}}
8192
*
8293
* @note Optional [[Function]]s, [[PartialFunction]]s and extractor objects
@@ -86,7 +97,7 @@ import scala.annotation.nowarn
8697
* | :---: | --- | --- | --- |
8798
* | from a [[PartialFunction]] | [[Predef.identity]] | [[lift]] | [[Predef.identity]] |
8899
* | 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]] |
90101
*  
91102
*
92103
* @define applyOrElseOrElse Note that calling [[isDefinedAt]] on the resulting partial function

0 commit comments

Comments
 (0)