Analisando Strings com Segurança em Números no Scala

Muito clichê

Em Java e Scala, você pode converter Stringpara números com bastante facilidade, mas como você pode imaginar, nem todas as strings serão convertidas em um número. Em ambas as linguagens, para converter suas strings com segurança, você precisa estar pronto para capturar um NumberFormatException. Isso geralmente cria muitos clichês, mesmo no scala.

Depois de capturar essa exceção, não está claro o que retornar no código. Em java, você retornaria um valor nulo ou algum valor padrão, mas isso nullé mau e está dando muita responsabilidade a uma função para deixá-la decidir qual é o valor padrão correto. A solução para isso no Scala é retornar um Optione retornar Noneno caso de uma exceção (ou usar Eitherse quiser mais informações sobre sua exceção). Você acaba com um código como este:

def safeStringToInt(str: String): Option[Int] = try {
Some(str.toInt)
} catch {
case NumberFormatException => None
}

Mas, falando sério, isso é muito clichê para uma operação simples que é usada com frequência. No entanto, os criadores do scala pensaram nesse tipo de caso e fornecem uma pequena ferramenta agradável para fazer isso try/catchque retorna um Option, e está tudo na classe do utilitário Exception :

def safeStringToInt(str: String): Option[Int] = {
import scala.util.control.Exception._
catching
(classOf[NumberFormatException]) opt str.toInt
}

Já está muito melhor!

Torne-o um utilitário

Embora seja muito menos clichê, você precisa ter esse método em seu contexto em algum lugar e, em seguida, chamá-lo. Se você veio do Java, pensaria em fazer isso com um método estático em alguma classe util. No Scala, há uma maneira muito mais simples de fazer isso: implícita!

Ok, nos meus dois últimos posts reclamei dos implícitos, mas estava falando de argumentos implícitos. Na verdade, existem alguns implícitos interessantes em scala: As
conversões implícitas permitem que você adicione funções postfix de forma transparente aos tipos existentes, sem ter que modificar suas fontes. No scala 2.10, isso ficou muito mais fácil com as classes implícitas :

object StringUtils {
implicit class StringImprovements(val s: String) {
import scala.util.control.Exception._
def toIntOpt = catching(classOf[NumberFormatException]) opt s.toInt
}
}

Você pode então chamar toIntOpt em qualquer String:import StringUtils._
scala "1234".toIntOpt //> Some(1234) "lkdsfasd".toIntOpt //> None