web-dev-qa-db-fra.com

Scala - supprimer le fichier s'il existe, la méthode Scala

Comment bien supprimer un fichier dans Scala, "la Scala"?

Par exemple, je peux utiliser quelque chose comme ça, très Java style:

  private def deleteFile(path: String) = {
    val fileTemp = new File(path)
    if (fileTemp.exists) {
       fileTemp.delete()
    }
  }

Comment serait-il implémenté dans Scala, dans une syntaxe plus fonctionnelle?

13
Johnny

Vous ne pouvez pas vous débarrasser des effets secondaires en faisant des opérations IO-, donc pas de bonnes façons fonctionnelles ici. Tous les éléments fonctionnels se terminent réellement lorsque vous commencez à interagir directement avec les utilisateurs/appareils, aucune monade ne peut vous aider à faire un effet secondaire externe; cependant, vous pouvez décrire (envelopper) les effets secondaires séquentiels en utilisant IO - comme les Monades.

En parlant de votre exemple, le code monad restylé peut ressembler à:

implicit class FileMonads(f: File) {
  def check = if (f.exists) Some(f) else None //returns "Maybe" monad
  def remove = if (f.delete()) Some(f) else None //returns "Maybe" monad
}

for {
  foundFile <- new File(path).check
  deletedFile <- foundFile.remove
} yield deletedFile

res11: Option[Java.io.File] = None

Mais c'est trop verbeux sans aucun avantage réel si vous juste voulez supprimer un fichier. Plus que ça, fileTemp.exists la vérification n'a aucun sens et n'est en fait pas fiable (comme l'a souligné @Eduardo). Donc, même en Scala la meilleure façon que je sache est FileUtils.deleteQuietly :

  FileUtils.deleteQuietly(new File(path))

Ou même

  new File(path).delete()

Il ne lèvera pas d'exception pour un fichier inexistant - il suffit de retourner false.

Si vous voulez vraiment quelque chose de plus Scala-way - regardez rapture.io par exemple:

  val file = uri"file:///home/work/garbage"
  file.delete()

Ou scala-io . Plus d'informations: Comment faire la création et la manipulation de fichiers dans un style fonctionnel?

P.S. Cependant, les IO-monades peuvent être utiles (contrairement à Some/None dans mon cas) lorsque vous avez besoin d'opérations asynchrones, donc un code naïf (sans chats/scalaz) ressemblerait à:

implicit class FileMonads(f: File) {
  def check = Future{ f.exists } //returns "Future" monad
  def remove = Future{ f.remove } //returns "Future" monad
}

for {
  exists <- new File(path).check
  _ <- if (exists) foundFile.remove else Future.unit
}

Bien sûr, dans le monde réel, il est préférable d'utiliser certains wrappers NIO comme FS2-io : https://lunatech.com/blog/WCl5OikAAIrvQCoc/functional-io-with- fs2-streams

31
dk14