if-statement - Xquery:相同的测试无论是在 switch/case 还是在 if/then/else 中都有不同的结果

标签 if-statement switch-statement case xquery flwor

我找不到以下内容的解释。我制作了这个测试脚本是为了解决 my previous question .

xquery version "3.0" ;
declare default function namespace 'local' ;

declare function local:is-img-only( $element as element() )  as xs:boolean {    
   ($element/child::*[1] instance of element(img)) 
   and (fn:not($element/child::*[2])) 
   and (fn:normalize-space($element) = '')
} ;

let $in-xml := <myxml>
   <p id="1">

      <img id="1"/>

   </p>
   <p id="2">
      <img id="1"/>
      hello
   </p>
   <p id="3">
      <img id="1"/>
   </p>
   <p id="4">
    <blockquote>hello</blockquote>
      <img id="1"/>
   </p>
   <p id="5">
      <img id="1"/>
      <img id="2"/>
   </p>
</myxml>

然后,使用 if then else 进行以下操作:

for $p in $in-xml/p
  return if (local:is-img-only($p)) 
    then $p/@id/fn:data() || ' has only an img child'
    else $p/@id/fn:data() || ' has not strictly an img child'

按预期返回:

1 has only an img child
2 has not strictly an img child
3 has only an img child
4 has not strictly an img child
5 has not strictly an img child  

而以下使用switch case

for $p in $in-xml/p
  return switch ($p)
    case (local:is-img-only($p)) return $p/@id/fn:data() || ' has only an img child'
    default return $p/@id/fn:data() || ' has not strictly an img child'

返回结果与预期不同:

1 has not strictly an img child
2 has not strictly an img child
3 has not strictly an img child
4 has not strictly an img child
5 has not strictly an img child

有什么解释吗?为什么Conditional Expressions的行为方式与 Switch Expressions 不同?

最佳答案

非常出色地找到了与您的问题相关的 XQuery 规范部分!这样就成功了一半。开关表达式确实与条件表达式有一些共同点,但也存在一些差异。

主要区别在于,条件表达式评估测试表达式以查看结果是真还是假,而开关表达式将一个表达式与一个或多个其他表达式进行比较 找到第一对相等的。使用伪代码,我们可以说明其中的差异。条件表达式中的所有逻辑都发生在一行上:

if ($EXPRESSION)

相比之下,switch 表达式的逻辑分布在许多行中:

switch ($EXPRESSION_A)
    case ($EXPRESSION_B) ...
    case ($EXPRESSION_C) ...
    case ($EXPRESSION_D) ...
    default ...

switch 表达式实际上执行一系列比较,我们可以将其表示为更多行条件表达式:

if (deep-equal($EXPRESSION_A, $EXPRESSION_B))
then ...
else 
    if (deep-equal($EXPRESSION_A, $EXPRESSION_C))
    then ...
    else ...
        if (deep-equal($EXPRESSION_A, $EXPRESSION_D))
        then ...
        else ... (: "default" :)

规范中描述了这两个表达式之间的本质区别,从它们描述处理每个表达式的“第一步”开始。而处理条件表达式的第一步是:

to find the effective boolean value of the test expression.

...处理 switch 表达式的第一步是:

to apply atomization to the value of the switch operand expression.

让我们回到具体示例,看一下条件的测试表达式和开关的 switch 操作数表达式:

  1. 您的条件测试表达式:

    if (local:is-img-only($p)) 
    
  2. 您的开关的操作数表达式:

    switch ($p)
    

条件的测试表达式返回 bool 值 - true()false() ,因此这个条件清楚地标出了其余代码的路径。

相比之下,switch 表达式的逻辑才刚刚从这个操作数表达式开始。首先,它找到操作数表达式的原子化值 - <p>绑定(bind)到 $p 的元素FLWOR 表达式中的变量。由于该值取决于哪个 <p>我们正在查看,原子化值将是空字符串( "" )、空格或 "hello" (或其某种组合,取决于源中的空白和边界空间声明)。然后,对 switch 的第一个 case 操作数进行求值和原子化。您的第一个 case 操作数如下:

case (local:is-img-only($p))

正如我们所记得的,这个表达式的计算结果是一个 bool 值。 switch 表达式执行的下一步是使用 fn:deep-equal 将 switch 操作数表达式的原子化值与 switch case 操作数的原子化值进行比较。功能。那么,我们实际上要求 XQuery 处理器执行以下比较:

deep-equal("", true())
deep-equal("hello", false())

在这两种情况下,比较都会返回 false() 。因此,我们的情况操作数中的这种比较总是失败,因此 switch 表达式回退到 default FLWOR 表达式的每次迭代中的子句。

模仿原始条件表达式结果的 switch 表达式如下:

for $p in $in-xml/p
  return switch(local:is-img-only($p))
    case (true()) return $p/@id/fn:data() || ' has only an img child'
    default return $p/@id/fn:data() || ' has not strictly an img child'

这会执行以下检查:

deep-equal(true(), true())
deep-equal(true(), false())

并返回与条件表达式相同的结果。

这对于 switch 表达式来说并不是特别引人注目的用途 - 因为我们正在有效地评估单个测试表达式。当您有许多值需要比较时,switch 表达式确实会发挥作用。该规范为我们提供了一个值得考虑的很好的开关表达式示例:

switch ($animal)
    case "Cow" return "Moo"
    case "Cat" return "Meow"
    case "Duck" return "Quack"
    default return "What's that odd noise?"

这比等效的条件表达式更具可读性和紧凑性:

if (deep-equal($animal, "Cow")) 
then "Moo"
else 
    if (deep-equal($animal, "Cat")) 
    then "Meow"
    else
        if (deep-equal($animal, "Duck"))
        then "Quack"
        else "What's that odd noise?"

或者更直接的解释:

if ($animal eq "Cow")
then "Moo"
else 
    if ($animal eq "Cat")
    then "Meow"
    else
        if ($animal eq "Duck")
        then "Quack"
        else "What's that odd noise?"

结果:如果您发现自己编写了一系列条件语句,并且比较的左侧始终相同,请考虑进行切换

关于if-statement - Xquery:相同的测试无论是在 switch/case 还是在 if/then/else 中都有不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48199042/

相关文章:

java - 从类内部调用类

ruby - 使 case/switch 返回值的快捷方式

java - java中字符串的不区分大小写的 HashMap

java - 如果我想使用 char 检查 Java 中的特殊字符,该怎么办?

C# IF 语句不排除字符串

c++ - 为什么 switch 语句不能应用于字符串?

c - switch 语句的非传统用法

case - 尝试在 Powerbuilder 中做一个 Case 语句

ruby - 使用 include 的简短 Ruby Case 语句?不管用

linux - bash if 语句 : Expression Syntax