2017-09-29 1 views
1

afin de mettre à jour un enfant sur un noeud XML, vous pouvez le faire (autre ref SO ticket manquant ici):Comment faire correspondre le cas undeprecated appliquer méthode de scala.xml.Elem

val node:Node = <item><category>1</category></item> 
val root = node match { 
    case Elem(p,l,a,s, child @ _*) ⇒ Elem(p,l,a,s,child.filter(_.label != "category") ++ <category>2</category>:_*) 
    case _ ⇒ node // error case 
} 

Cette donne un avertissement dépréciée, comme on doit utiliser la méthode Elem avec désignation explicite de minimizeEmpty comme 5ème paramètre:

val node:Node = <item><category>1</category></item> 
val root = node match { 
    case Elem(p,l,a,s,m,child @ _*) ⇒ Elem(p,l,a,s,m,child.filter(_.label != "category") ++ <category>2</category>:_*) 
    case _ ⇒ node // error case 
} 

Cela ne fonctionne pas, car il applique toujours la Deconstructing de la méthode apply sans paramètre booléen explicite, par conséquent m obtient toujours le type Node et rien ne convient.

Alors, comment puis-je aider le compilateur à sélectionner la bonne méthode Constructor/apply? (Scala 2.12.1)

ne fonctionne pas:

case Elem(p,l,a,s,m:Boolean,child @ _*) 
case Elem(p,l,a,s,m @(_:Boolean),child @ _*) 
case Elem(p,l,a,s,m @Boolean,child @ _*) 

me disent que m doit être Node

Répondre

1

Si vous regardez l'avertissement de dévalorisation, il est avec le compagnon méthode Appliquons objet, et pas avec le constructeur de correspondance de motif:

> set scalacOptions += "-deprecation" 
> console 
scala> import scala.xml._ 

scala> val node:Elem = <item><category>1</category></item> 

scala> node match { 
     case Elem(p,l,a,s, child @ _*) ⇒ Elem(p,l,a,s,child.filter(_.label != "category") ++ <category>2</category>:_*) 
     } 
<console>:17: warning: method apply in object Elem is deprecated: Use the other apply method in this object 
    case Elem(p,l,a,s, child @ _*) ⇒ Elem(p,l,a,s,child.filter(_.label != "category") ++ <category>2</category>:_*) 
           ^

Il pourrait être utile d'utiliser simplement un paramètre variable de liaison avec @:

scala> node match { 
    | case e @ Elem(p,l,a,s, child @ _*) ⇒ Elem(p,l,a,s,e.minimizeEmpty,child.filter(_.label != "category") ++ <category>2</category>:_*) 
    | } 
res1: scala.xml.Elem = <item><category>2</category></item> 

Je suis un peu surpris le motif correspond pour Elem a ce défaut. Pour une raison quelconque, Elem a été converti en un objet compagnon avec une méthode apply, en 2007, à partir d'une classe de cas. En 2012, la deuxième méthode apply a été ajoutée et obsolète la première.

Les fonctions dans Scala supportent les varargs, et elles fonctionnent bien. Les classes de cas dans Scala prennent également en charge les varargs. Dans ce cas, c'est avec apply méthodes utilisant varargs, et il y en a deux. Le compilateur prend en charge l'utilisation de plusieurs méthodes apply, mais la manière dont cela interagit avec varargs peut rendre la correspondance de modèle difficile. Je ne pense pas que les responsables de scala-xml aient compris l'impact de leurs changements, en ce qui concerne la correspondance de modèle, lorsqu'ils ont ajouté une seconde méthode d'application pour ajouter de nouveaux paramètres.

+0

Cette dernière solution est presque ce que j'ai utilisé, merci pour cette amélioration. Quand j'ai lu votre réponse correctement, c'est un bug/défaut dans Scala? J'ai été témoin de cela auparavant avec des fonctions surchargées où l'on avait un paramètre '*'? – Jan

+1

@Jan Bonne question. J'ai répondu en ajoutant un autre paragraphe à la réponse ci-dessus. – ashawley

+0

notre belle solution avec 'e @ Elem ...' ne fonctionne pas, quand le type de 'node' est en fait' Node' ... Donc je m'en tiens à ma variante 'node.asInstanceOf [Elem] .minimizeEmpty' :) – Jan