Reputation: 34403
One of the reasons why Scalaz Maybe was added was to get rid of get:
Some differences from std lib Option:
- No unsafe get method
I understand get
can be unsafe, but sometimes is is safe (in a code which has verified before the Option
is not empty). There are some situations where one can easily stay away from using get
, but sometimes it is not so obvious to me. What would be the alternatives to get
in the following code?
def point(cursor:Int) : Option[XY]
def paste(cs: Seq[Int]) = {
if (validateSelection(cs)) {
cs.size match {
case 2 => // between two points
// editablePoint returning Option for general case,
// but here it is known to succeed as validateSelection passed
val beDiff = point(cs.head).get.xy - point(cs.last).get.xy
...
case _ =>
...
}
...
}
Upvotes: 2
Views: 565
Reputation: 12123
To get rid of the quasi-safe get
, you have to refactor your validateSection
. In your example it probably returns a Boolean
:
def validateSection(cs: Seq[Int]): Boolean
Yet, you could return an evidence, that cs
is valid:
/* Returns the first and last values of the sequence,
* if the sequence's length == 2. Otherwise `Empty`.
*/
def validateSection(cs: Seq[Int]): Maybe[(Int, Int)]
Then you could refactor your snippet as:
def paste(cs: Seq[Int]) = {
match validateSelection(cs) {
case (first, last) =>
val beDiff = first - last
...
case _ =>
...
}
...
}
EDIT You can take the idea further: Create auxillary types to get away of function's partiality.
The point
returns Option[XY]
, i.e. it's partial. We should try to make input parameters more precise, so point
can be total, i.e. return XY
. Without knowing precise specification I can only sketch the solution:
case class Selection(/* ... */)
/* Constructed from `Selection` */
case class Cursor()
object Selection {
def first: Cursor = ???
def last: Cursor = ???
}
/* If `cs` is valid, we return a `ValidSelection`, othersise `Empty`. */
def validateSelection(cs: Seq[Int]): Maybe[Selection]
/* With more precise type, we can have total `point`. */
def point(cursor: Cursor): XY
This approach may look boilerplaty at first, but here we use the advantage of having the type system. Avoid stringly typed or List-typed programming.
Upvotes: 1