Scala - delete file if exist, the Scala way
You can't get rid of side effects while doing IO
-operations, so no good functional ways here. All functional stuff is actually ends when you start to interact with user/devices directly, no monad can help you to do one external side-effect; however, you can describe (wrap) sequential side-effects using IO-like Monads.
Talking about your example, monad-restyled code may look like:
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
But that's too verbose without any real advantages if you just want to delete one file. More than that, fileTemp.exists
check has no sense and actually isn't reliable (as @Eduardo pointed out). So, even in Scala the best way I know is FileUtils.deleteQuietly:
FileUtils.deleteQuietly(new File(path))
Or even
new File(path).delete()
It won't throw an exception for non-existent file - just return false
.
If you really want something more Scala-way - look at rapture.io for example:
val file = uri"file:///home/work/garbage"
file.delete()
Or scala-io. More info: How to do File creation and manipulation in functional style?
P.S. However IO-monads might be useful (unlike Some/None in my case) when you require asynchronous operations, so naive code (without cats/scalaz) would look like:
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
}
Of course, in the real world, it's best to use some NIO-wrappers like FS2-io: https://lunatech.com/blog/WCl5OikAAIrvQCoc/functional-io-with-fs2-streams