一般比较与价值比较

General Comparisons vs Value Comparisons

为什么 XQuery 以不同的方式处理以下表达式?

XQuery 规范中解释了此效果。对于 XQuery 3,它在 3.7.1, Value Comparisons 章中(我添加的突出显示):

  1. Atomization is applied to the operand. The result of this operation is called the atomized operand.
  2. If the atomized operand is an empty sequence, the result of the value comparison is an empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.

因此,如果您要比较两个单个元素序列(或标量值,等于它们),您将按预期收到 true/false 值:

  • 1 eq 2false
  • 2 eq 2true
  • (1) eq 2false
  • (2) eq 2true
  • (2) eq (2)true
  • 等等

但是,如果一个或两个操作数是空列表,您将收到空列表:

  • () eq 2()
  • 2 eq ()()
  • () eq ()()

此行为允许您传递空序列,在这里可以用作一种 null 值。正如@adamretter 在评论中添加的那样,空序列 () 的有效布尔值是 false,所以即使你 运行 像 if ( () eq 2) ... 这样的东西,你也不会观察到有什么惊喜。

如果任何操作数包含一个以上元素的列表,则为类型错误。

一般比较$sequence1 = $sequence2 测试 any 元素在 $sequence1 中是否与 $sequence2。由于这在语义上已经支持任意长度的序列,因此不必应用原子化。

为什么?

区别在于运营商签名的要求。如果您以基于集合的方式比较任意长度的序列,则没有理由为空序列包含任何特殊情况——如果包含空序列,则根据定义自动进行比较 false

对于比较单个值的运算符,必​​须考虑传递空序列的情况;决定是不引发错误,但 return 一个等于 false 的值:空序列。这允许在值未知时使用空序列作为一种 null 值;与未知值相比的任何东西都不能是 true,但不能(必然)为假。如果需要,您可以检查 empty(...) 结果,如果是,则要比较的值之一是未知的;否则他们就是不同的。在 Java 和其他语言中,null 值将用于实现类似的结果,在 Haskell 中有 Data.Maybe.