Попытка избежать двух пробных блоков в моем методе - PullRequest
0 голосов
/ 14 июля 2020

Как мне избежать дублирования условия if в моем коде:

  def download() =
    Action {
      val out = new FileWriter("/tmp/foo.txt")
      Try {
        val chars = new Array[Char](1024)
        util.Arrays.fill(chars, '.')
        chars(1024) = '\n'
        out.write(chars)
      } match {
        case Failure(_) =>
          if (out != null) out.close()
          println("failed")
        case Success(_) =>
          if (out != null) out.close()
          println("success")
      }
    }

Я попытался адаптироваться из следующего:

  def download() =
    Action {
      Try {
        val out = new FileWriter("/tmp/foo.txt")
        try{
        val chars = new Array[Char](1024)
        util.Arrays.fill(chars, '.')
        chars(1024) = '\n'
        out.write(chars)
        } if (out != null) out.close()
      } match {
        case Failure(_) =>
          println("failed")
        case Success(_) =>
          println("success")
      }
    }

Но так у меня есть Java try внутри Scala Try, что кажется неправильным. Как мне избежать двух блоков попыток? В основном я просто хочу, чтобы ресурс, который я приобрел, был очищен после завершения выполнения метода.

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Почему бы просто не переместить out.close() за пределы результата блока Try? Если одна и та же проверка выполняется независимо от того, успешна она или нет, я не вижу пользы от ее выполнения. Примерно так:

def download() = Action {
  val out = new FileWriter("/tmp/foo.txt")

  Try {
    val chars = new Array[Char](1024)
    util.Arrays.fill(chars, '.')
    chars(1024) = '\n'
    out.write(chars)
  } match {
    case Failure(_) =>
      println("failed")
    case Success(_) =>
      println("success")
  }

  if (out != null) out.close()
}
1 голос
/ 14 июля 2020

Если вы не можете использовать Using, вы можете использовать try-catch-finally:

def download() =
  Action {
    val out = new FileWriter("/tmp/foo.txt")
    try {
      val chars = new Array[Char](1024)
      util.Arrays.fill(chars, '.')
      chars(1024) = '\n'
      out.write(chars)
      println("success")
    } catch {
      case _: Throwable =>
        println("failed")
    } finally {
      out.close()
    }
  }

или образец ссуды:

def withFileWriter[A](str: String)(f: FileWriter => A): Try[A] = Try {
  val out = new FileWriter("/tmp/foo.txt")
  try {
    f(out)
  } finally {
    out.close()
  }
}

withFileWriter("/tmp/foo.txt"){ out =>
  util.Arrays.fill(chars, '.')
  chars(1024) = '\n'
  out.write(chars)
} match {
  case Failure(_) =>
    println("failed")
  case Success(_) =>
    println("success")
}

Если у вас есть Cats Effect (и если вы замените Try с чем-то законным) вы можете использовать Ресурс

val resource = Resource.make {
  IO(new FileWriter("/tmp/foo.txt"))
} { out =>
  IO(out.close())
}

resource.use(out => IO {
  util.Arrays.fill(chars, '.')
  chars(1024) = '\n'
  out.write(chars)
}).attempt.map {
  case Failure(_) =>
    println("failed")
  case Success(_) =>
    println("success")
}.unsafeRunSync
1 голос
/ 14 июля 2020

Используя scala 2.13, вы можете написать следующее с помощью scala.util.Using

import scala.util.Failure
import scala.util.Success
import scala.util.Using

Using(new FileWriter("/tmp/foo.txt")) { out =>
  val chars = new Array[Char](1024)
  java.util.Arrays.fill(chars, '.')
  chars(1023) = '\n'
  out.write(chars)
} match {
  case Failure(_) =>
    println("failed")
  case Success(_) =>
    println("success")
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...