Je suis très nouveau à Scala et j'essaie toujours de m'habituer à la syntaxe et à la style, c'est probablement une question très simple.
Je travaille avec une base de code où il y a beaucoup de cas classes remplies d'options telles que: p> dans l'exemple ci-dessus, comment allez-vous retourner combien d'argent est dans une personne code> ' Code> Pantalon Code>
Pocket CODE>, S'ils portent des pantalons ... avec des poches, et s'ils ont de l'argent du tout? P> P>
4 Réponses :
Un bon moment pour pour les compréhensions : < Pré> xxx pré>
Equivalement Vous pouvez écrire ce qui suit, pour lequel le premier code est syntaxique sucre (ignorant certaines subtilités): p> (je suis Pas totalement sûr si vous pouvez écrire la dernière expression à l'aide des caractères génériques _ code>, comme je l'ai fait). p> p>
Super merci! L'approche de compréhension est en fait exactement ce que j'essayais de faire, mais la structure que je travaille n'est pas aussi propre que l'exemple que j'ai donné ci-dessus. Au moins cela confirme que je suis sur la bonne voie.
La réponse de Ziggystar est ce que j'utiliserais, mais pour l'exhaustivité, la correspondance des motifs peut également être utilisée, par exemple
val someCash: Option[Cash] = person match { case Person(Some(Pants(Some(Pocket(Some(cash)))))) => Some(cash) case _ => None }
La question ne mentionnait pas modifier em> les données, mais lorsque vous devez le faire, vous trouverez rapidement la bibliothèque Scala ne dispose pas des outils pour faciliter la tâche (lorsque les données sont immuables) . Si vous n'avez pas encore vécu cela, essayez d'écrire une fonction qui remplacera ou modifiera la valeur comme décrit dans Tony Morris ' Objectifs asymétriques à Scala , lentilles em> sont une solution appropriée à ce problème. P> Voici un exemple de la manière dont nous pouvons accéder à l'accès et à la mise à jour de la valeur code> code> d'une personne Premier, certains chaudières: définir l'instance de lentille pour chaque champ des classes de boîtier. Nous ne pouvons pas composer toutes ces lentilles, cependant, parce que la plupart des champs sont enveloppés dans les types code> (code> (code> p> lentilles partielles em> à la rescousse: celles-ci nous permettent d'accéder à et mettre à jour les parties d'une structure qui peut ne pas exister em>, telle que la valeur Nous pouvons utiliser la fonction code> à pied code> de Scalaz 7 pour créer une lentille partielle visualisant chaque champ facultatif. Afin de composer une lentille partielle avec l'une de nos objectifs ordinaires, nous devons toutefois accéder à l'instance d'objectif partielle équivalente pour la lentille ordinaire, à l'aide de la méthode code> du
en espèces code> détenu par un
personne code> , en utilisant les types définis dans la question.
en espèces code> à l'aide de la lentille code> et
Plens code> (objectif partiel) des implémentations de Scalaz-Seven Branche de Scalaz. P>
A @ - @ b code> signifie identique à
objectif [A, B] code>. p>
une valeur code> d'une option code> ou de la tête
ou de la tête code > d'une liste code> code>. p>
partielle code> sur chaque lentille
.
scala> val ben = Person(None)
ben: Person = Person(None)
scala> someCashValue.mod(_ + ", zero, nada", ben)
res4: Person = Person(None)
Scalaz 7 a changé un peu donc ici est un autre exemple:
object PartialLensExample extends App { import scalaz._ import Lens._ import PLens._ case class Bar(blub: Option[String]) case class Foo(bar: Option[Bar]) // normal lenses for getting and setting values val fooBarL: Foo @> Option[Bar] = lensg(foo â bar â foo.copy(bar = bar), _.bar) val barBlubL: Bar @> Option[String] = lensg(bar â blub â bar.copy(blub = blub), _.blub) // compose the above as 'Partial Lenses', >=> is just an alias for 'andThen' val fooBarBlubL: Foo @?> String = fooBarL.partial >=> somePLens >=> barBlubL.partial >=> somePLens // try it val foo = Foo(Some(Bar(Some("Hi")))) println(fooBarBlubL.get(foo)) // Some(Hi) println(fooBarBlubL.set(foo, "Bye")) //Foo(Some(Bar(Some(Bye)))) // setting values val foo2 = Foo(None) println(fooBarL.set(foo2, Some(Bar(None)))) // Foo(Some(Bar(None))) }
Une bonne réponse, mais une grosse trottoir ici lors de la définition de ces valeurs imbriquées est la suivante: que si des valeurs sont Aucun code>? Le
Plens code> dans votre exemple n'autorisera que
Blub: option [string] code> à attribuer si
blub code> a déjà
certains < / Code> Valeur i>. J'ai trouvé des transitions d'état monadiques peut initialiser les membres de niveau supérieur, mais je ne suis pas clair comment cela serait fait pour les personnes plus bas.
hmm, oui. J'ai mis à jour la réponse pour la définition d'une barre sur une FOO, mais je vois la question de la définition de la valeur de Blub dans la barre - je devrai réfléchir à ce sujet.
A Bogosity des transitions d'état en utilisant Plens code> instances
est le mieux que je pouvais Faites, initialisez les propriétés selon les besoins (ce qui est logique, surtout à la lumière de La réponse impliquant des pantalons @ Ben-James a donné). Cela me frappe comme trop laborieux et ça n'a pas échoué, alors j'imagine qu'il y a une meilleure approche.
Après avoir réfléchi à cela, je pense que le comportement est correct tel qu'il est. Ce problème se résume à une lentille définissant une valeur sur une option. Si l'option n'en est pas, il n'y a rien à définir. Cependant, je peux également voir qu'il serait utile pour une lentille de prendre en charge la définition d'une valeur dans une option contenue par un autre type, comme un raccourci peut-être. Comme il est debout, vous devez définir l'option dans son ensemble.