Todos heredamos de nuestros padres biológicos un conjunto de instrucciones químicas conocidas como ADN que influyen en cómo se construyen nuestros cuerpos. ¡Toda la vida conocida depende del ADN!
Nota: No necesitas entender nada sobre los nucleótidos ni el ADN para completar este ejercicio.
El ADN es una larga cadena de otras sustancias químicas, y las más importantes son los cuatro nucleótidos: adenina, citosina, guanina y timina. ¡Una sola cadena de ADN puede contener miles de millones de estos cuatro nucleótidos, y el orden en que aparecen es importante! Al orden de estos nucleótidos en un fragmento de ADN lo llamamos «secuencia de ADN».
Representamos una secuencia de ADN como una colección ordenada de estos cuatro nucleótidos, y una forma común de hacerlo es con un string de caracteres como «ATTACG» para una secuencia de ADN de 6 nucleótidos. «A» para la adenina, «C» para la citosina, «G» para la guanina y «T» para la timina.
Dado un string que representa una secuencia de ADN, cuenta cuántos hay de cada nucleótido. Si el string contiene caracteres que no son A, C, G o T, entonces no es válido y debes indicar un error.
Por ejemplo:
"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2
"INVALID" -> error
Un uso común de Either es indicar un cálculo que posiblemente resulte en un error
(si el error en sí no te interesa, quizás el tipo Option, más simple, sea una mejor opción).
Cuando no hay error, el resultado suele ser un Right (regla mnemotécnica: el valor correcto),
mientras que un error es un Left, por ejemplo un Left[String] que contiene un mensaje de error.
Ten en cuenta que en Scala 2.12 Either está sesgado hacia la derecha por defecto, así que funciona como esperas en operaciones como filter, map, flatMap o en una comprensión for.
Si no conoces Either, puedes leer este tutorial. Pero ten en cuenta que este tutorial trata sobre versiones de Scala anteriores a la 2.12. Para Scala 2.12 puedes ignorar sin problema RightProjection y omitir .right.
Either es una llamada mónada que cubre un «aspecto computacional»,
en este caso el manejo de errores.
El uso correcto de las mónadas puede dar como resultado un código muy conciso, pero elegante
y legible. El uso incorrecto puede llevar fácilmente a lo contrario.
Mira este video para aprender más.
Hay algunas reglas generales para Either:
def add1(x: Int): Either[String, Int] = Right(x + 1)
es mejor tener
def add1(x: Int): Int = x + 1
(existe Either.map para aplicar funciones así de simples,
así que no tienes que llenarlas de Either).
2. No hagas «unwrap» si en realidad no lo necesitas.
A menudo hay funciones integradas para lo que buscas. Señales de un unwrap
prematuro son isLeft/isRight o la coincidencia de patrones. Por ejemplo, en lugar de
val x: Either[String, Int] = ...
if (x.isRight) x.right.get + 1 else x.left.get
// or
x match {
case Right(n) => n + 1
case Left(s) => s
}
es mejor tener
x fold (identity, _ + 1)
for, ¡y son una maravilla!
Esto es recomendable cuando quieres «componer» varias instancias de Either. En lugar deval xo: Either[String, Int] = ...
val yo: Either[String, Int] = ...
val zo: Either[String, Int] = ...
xo.flatMap(x =>
yo.flatMap(y =>
zo.map(z =>
x + y + z)))
es mejor tener
for {
x <- xo
y <- yo
z <- zo
} yield x + y + z
Regístrate en Exercism para aprender y dominar Scala con 95 ejercicios y mentoría humana real, todo gratis.