I have a functionality with a field of type Option[Path], then the data type of this field changed to Option[String]. I would like to rewrite this functionality without using matching, is that possible to do so?
The way it used to look like with samplePath: Option[Path]
samplePath.fold(new File(getResource("sample").getPath))(_.toFile)
The way it looks like with samplePath: Option[String]
def transformToPath(path: Option[String]): Option[Path] = {
path match {
case Some(st) => Some(Paths.get(st))
case None => None
}
}
transformToPath(samplePath).fold(new File(getResource("sample").getPath))(_.toFile)
The most naive solution would be to .map
the path:
def transformToPath(path: Option[String]): Option[Path] =
path.map(path => Paths.get(path))
A better way would be to wrap the inner expression with a Try[A]
:
def transformToPath(path: Option[String]): Option[Path] =
path.flatMap(path => Try(Paths.get(path)).toOption)
Note that this will not signal an error occurred in Paths.get
(which can throw an exception). Ideally, we should also propagate that to the caller:
def transformToPath(path: Option[String]): Either[Throwable, Option[Path]] =
path.fold[Either[Throwable, Option[Path]]](Right(None))(
path => Try(Paths.get(path)).map(Option(_)).toEither
)
Now, in case Paths.get
throws we get a Left
with an Exception
.
Perhaps even better would be eliminating the Option[String]
input an requiring a strict String
to be passed in, which helps us avoid the redundant Option[Path]
wrapper and return a direct Path
object in case we successfully constructed it:
def transformToPath(path: String): Either[Throwable, Path] =
Try(Paths.get(path)).toEither
Now, this would require the external caller .map
over the Option[String]` before calling this method:
val result = Option(someStringFromJavaLand).map(transformToPath)