这是 scala.xml.Elem 中的错误吗?

发布于 2024-10-10 12:01:35 字数 634 浏览 1 评论 0原文

将 Set[String] 映射到 Set[Elem] 的属性对于一个属性可以正常工作,但当共享其中一个属性时,对于多个属性似乎会失败:

scala> val s1=Set("A","B","C")
s1: scala.collection.immutable.Set[java.lang.String] = Set(A, B, C)

scala> s1.map((a:String)=>{<X w={a}></X>})
res3: scala.collection.immutable.Set[scala.xml.Elem] = Set(<X w="A"></X>, <X w="B"></X>, <X w="C"></X>)

scala> s1.map((a:String)=>{<X w={a} k="SSS"></X>})
res4: scala.collection.immutable.Set[scala.xml.Elem] = Set(<X k="SSS" w="A"></X>)

B & 发生了什么? C?

或者我对 Elems 上的 equals 的理解是错误的?

Mapping a Set[String] to attributes of a Set[Elem] works fine with one attribute, but seems to fail with multiple attributes when one of them is shared:

scala> val s1=Set("A","B","C")
s1: scala.collection.immutable.Set[java.lang.String] = Set(A, B, C)

scala> s1.map((a:String)=>{<X w={a}></X>})
res3: scala.collection.immutable.Set[scala.xml.Elem] = Set(<X w="A"></X>, <X w="B"></X>, <X w="C"></X>)

scala> s1.map((a:String)=>{<X w={a} k="SSS"></X>})
res4: scala.collection.immutable.Set[scala.xml.Elem] = Set(<X k="SSS" w="A"></X>)

What happened to B & C?

Or is my understanding of equals on Elems wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

零時差 2024-10-17 12:01:36

我认为问题出在 xml.MetaData 或其子类 xml.Attribute 中。比较两个 Elem 时,会检查 xml 前缀、标签、属性和 Node 子级是否相等。

现在,xml.MetaData 在下面有一种奇怪的实现,它包含自身,同时包含属性的链接列表。这意味着,例如:

scala >val elem = <e x="a" y="b"></e>
elem: scala.xml.Elem = <e y="b" x="a"></e>

scala> elem.attributes
res50: scala.xml.MetaData =  y="b" x="a"

scala> elem.attributes.toSet
res51: Set[scala.xml.MetaData] = Set( y="b" x="a",  x="a")

例如,它生成一个自身列表,并删除了 head 属性。

MetaData 中的相等性检查看起来像这样

this.toSet == other.toSet

,工作正常,但在 Attribute 类中被覆盖。 (我们在 REPL 中看不到它,但我们的 elem.attributes 确实是一个 Attribute。)在那里,代码只执行此

(this.pre == other.pre) && (this.key == other.key) && (this.value sameElements other.value)

操作,如果属性列表之前已转换为 Set,但事实并非如此,因此仅检查属性列表中的第一个元素是否相等。因此,如果两个 xml.Elem 的内部属性链表中的 head 元素恰好是相同的元素,则它们将相等。

I think the problem lies in xml.MetaData or its subclass xml.Attribute. When comparing two Elems, it is checked for equality of the xml prefix, the label, the attributes and the Node’s children.

Now, xml.MetaData has kind of a strange implementation underneath, it contains itself and at the same time a linked list of attributes. That means that, for example:

scala >val elem = <e x="a" y="b"></e>
elem: scala.xml.Elem = <e y="b" x="a"></e>

scala> elem.attributes
res50: scala.xml.MetaData =  y="b" x="a"

scala> elem.attributes.toSet
res51: Set[scala.xml.MetaData] = Set( y="b" x="a",  x="a")

E.g. it generates a list of itself with the head attribute removed.

The equality check in MetaData looks like this

this.toSet == other.toSet

which works okay but is overridden in the Attribute class. (We can’t see it in the REPL, but our elem.attributes really is an Attribute.) There, the code only does this

(this.pre == other.pre) && (this.key == other.key) && (this.value sameElements other.value)

Which would be fine, if the attributes list were converted to a Set before but it isn’t and so only the first element in the attributes list is checked for equality. And thus, if the head element in the internal linked list of attributes happens to be the same element for two xml.Elems, they will be equal.

凤舞天涯 2024-10-17 12:01:35

这确实是一个错误,尽管是一个非常奇怪的错误。我猜这是 Set 中的错误,而不是 Elem 中的错误,但在这一点上我无法与任何权威人士交谈。

This does appear to be a bug, albeit a very strange one. I would guess it's a bug in Set and not Elem, but I can't speak with any authority on that point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文