使用IF将变量绑定到两个值中的一个?

18
在以下的SPARQL查询中,我不确定如何使用if将两个字符串中的一个绑定到变量?result。我听说有“in scope”和“out of scope”的概念,但我并没有真正看到差别。我也尝试在select行中放置if子句,但它也没有起作用。如何修改此查询以根据条件将?result绑定到两个字符串中的一个?
SELECT ?result
WHERE{
    ?chain rdf:type rdfs:Property .
    ?chain rdfs:domain <http://www.vs.cs.hs-rm.de/ontostor/SVC#MDiskGroup> .
    ?chain rdfs:range <http://www.vs.cs.hs-rm.de/ontostor/SVC#IOgroup> .
    ?this ?chain ?arg .
    ?arg io:id ?var .
    IF(?var = "0"^^xsd:integer,
       BIND("    *"^^xsd:string AS ?result),
       BIND(""^^xsd:string AS ?result)) .
}
1个回答

31

在SPARQL中,if运算符不像在某些编程语言中一样是一个语句,而是一个“函数形式”,用于创建一个带有特殊求值语义的表达式if(test,a,b)a,如果test为真,则为b,如果test为假。正如文档所述:

17.4.1.2 IF

rdfTerm  IF (expression1, expression2, expression3)

IF 函数首先计算第一个参数,将其解释为有效布尔值,如果EBV为真,则返回 expression2 的值,否则返回 expression3 的值。只有一个表达式(expression2或expression3)会被计算。如果计算第一个参数时出现错误,则在 IF 表达式的评估中引发错误。

例如:假设在某个查询解决方案中,?x = 2,?z = 0,而且 ?y 没有被绑定:

IF(?x = 2, "yes", "no")     returns "yes"
IF(bound(?y), "yes", "no")  returns "no"
IF(?x=2, "yes", 1/?z)       returns "yes", the expression 1/?z is not evaluated
IF(?x=1, "yes", 1/?z)       raises an error
IF("2" > 1, "yes", "no")    raises an error
因此,if并不像在某些编程语言中一样是一个语句,而只是一个函数(懒惰地计算),它接受三个参数并返回一个值。SPARQL是一种查询语言,没有会被执行的语句;它是用于在图形中匹配模式并将变量绑定到值的查询语言。所以if是一个函数,如果第一个参数为真,则返回第二个参数,否则返回第三个参数。通常,您会将函数的值与变量绑定。
bind( function(args...) as ?variable )

这种情况也不例外。您将调用if函数并将其结果绑定到变量上。

bind( if(condition,then,else) as ?result )

在你的情况下,这意味着你将使用以下查询。我添加了一些换行符以帮助可读性,但它们并不是必要的。在SPARQL查询中,整数是一个带有xsd:integer类型的文字的简写,因此我还使用了(感谢RobV的评论)0代替"0"^^xsd:integer。(请参见 2.3.2 匹配带有数字类型的文字。)

bind(if(?var = 0,
        "    *"^^xsd:string,
        ""^^xsd:string )
     as ?result)
如果我们想要更进一步缩短代码,我们可以使用 xsd:string 作为构造函数,并执行以下操作(请参见17.5 XPath构造函数):
bind(xsd:string(if(?var = 0,"    *", "")) as ?result)

如果你习惯于做像这样的事情,这可能一开始看起来有点奇怪

String result;
if ( var == 0 ) {
  result = "case 1";
}
else {
  result = "case 2";
}
但是实际上许多编程语言提供了一个三元运算符,使你可以做更短的操作。
String result = (var == 0) ? "case 1" : "case 2";

相反,这就是你使用SPARQL获得的功能。


你可以简化一下为 BIND(IF(?var = 0, " *"^^xsd:string, ""^^xsd:string)),即不需要显式地声明整数类型,而是依赖于SPARQL语法中的整数纯文字快捷方式。 - RobV
1
@RobV 啊,谢谢,我不记得默认的数字类型是什么(是xsd:integerxsd:int等)。如果我们在进行代码高尔夫比赛,我们也可以使用xsd:string作为构造函数,并且执行bind( xsd:string(if(?var = 0, " *", "")) as ?result)。:) - Joshua Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接