Nous héritons tous de nos parents biologiques un ensemble d'instructions chimiques appelé ADN, qui influencent la façon dont notre corps se construit. Toute forme de vie connue dépend de l'ADN !
Remarque : tu n'as pas besoin de comprendre quoi que ce soit aux nucléotides ou à l'ADN pour faire cet exercice.
L'ADN est une longue chaîne d'autres produits chimiques, et les plus importants sont les quatre nucléotides : l'adénine, la cytosine, la guanine et la thymine. Une seule chaîne d'ADN peut contenir des milliards de ces quatre nucléotides, et l'ordre dans lequel ils apparaissent est important ! On appelle l'ordre de ces nucléotides dans un fragment d'ADN une « séquence d'ADN ».
On représente une séquence d'ADN comme une collection ordonnée de ces quatre nucléotides, et une façon courante de le faire est d'utiliser une string de caractères telle que « ATTACG » pour une séquence d'ADN de 6 nucléotides. « A » pour l'adénine, « C » pour la cytosine, « G » pour la guanine et « T » pour la thymine.
À partir d'une string qui représente une séquence d'ADN, compte combien de fois chaque nucléotide apparaît. Si la string contient des caractères autres que A, C, G ou T, elle est invalide et tu dois signaler une erreur.
Par exemple :
"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2
"INVALID" -> error
Un usage courant de Either consiste à indiquer un calcul qui peut éventuellement produire une erreur (si l'erreur elle-même ne t'intéresse pas, le type Option, plus simple, est peut-être un meilleur choix). En l'absence d'erreur, le résultat est généralement un Right (mnémonique : la valeur « right »), tandis qu'une erreur donne un Left, par exemple un Left[String] contenant un message d'erreur. Note qu'en Scala 2.12, Either est orienté à droite par défaut, si bien qu'il se comporte comme attendu pour des opérations comme filter, map, flatMap ou dans une for-comprehension. Si Either ne t'est pas familier, tu peux lire ce tutoriel. Mais sache que ce tutoriel porte sur des versions de Scala antérieures à la 2.12. Avec Scala 2.12, tu peux ignorer RightProjection sans crainte et omettre .right. Either est ce qu'on appelle une monade, qui couvre un « aspect de calcul », ici la gestion des erreurs. Un bon usage des monades peut donner du code très concis, mais aussi élégant et lisible. Un usage inapproprié peut facilement produire le contraire. Regarde cette vidéo pour en savoir plus.
Il existe quelques règles empiriques pour Either :
def add1(x: Int): Either[String, Int] = Right(x + 1)
mieux vaut écrire
def add1(x: Int): Int = x + 1
(il existe Either.map pour appliquer ce genre de fonctions simples, tu n'as donc pas besoin de les encombrer avec Either).
isLeft/isRight ou le pattern matching. Par exemple, plutôt queval 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
}
mieux vaut écrire
x fold (identity, _ + 1)
Either. Plutôt queval 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)))
mieux vaut écrire
for {
x <- xo
y <- yo
z <- zo
} yield x + y + z
Inscris-toi sur Exercism pour apprendre et maîtriser Scala avec 95 exercices, et un vrai mentorat humain, le tout gratuitement.