Search code examples
scalapathoption-type

Convert Option[String] to Option[Path]


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)

Solution

  • 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)