【问题标题】:Execute function in FLWOR without using 'let'在 FLWOR 中执行函数而不使用“let”
【发布时间】:2014-09-04 22:01:27
【问题描述】:

假设我创建了一张地图:

let $map := map:map()

如何在不使用let 的情况下在该地图中添加内容?通常我必须做类似

的事情
let $map := map:map()
let $useless-var := map:put($map, $key, $value)

如果我想执行某事而不关心返回值,我仍然必须存储结果,这似乎很奇怪。我在这里错过了什么?

注意:重要的部分不是 map(),而是我无法运行函数而不将结果存储在一些无意义的变量中。

【问题讨论】:

    标签: xquery marklogic


    【解决方案1】:

    一种方法是将函数作为序列中的项执行,其中序列中只有一项(通常是第一项或最后一项)为赋值或返回提供实际值,如下所示:

    let $roundedX := (
        math:floor($x),
        local:function1(...),
        local:function2(...)[false()],
        ...
        )
    ...
    return (
        local:functionA(...),
        local:functionB(...)[false()],
        ...,
        $roundedX * 10
        )
    

    如果函数返回一个你想丢弃的值,只需使用一个假谓词,就像上面的两个函数一样。

    当然,这种方法只对有副作用的函数有用。

    【讨论】:

    • 如果函数返回一个空序列(如map:put()),你甚至不需要谓词。
    【解决方案2】:

    除非需要,否则不要使用 FLWOR。在我看来,FLWOR 表达式有些过度使用。我经常看到这样的表达:

    let $a := current-time()
    return $a
    

    ...什么时候写也可以:

    current-time()
    

    另请参阅:http://blakeley.com/blogofile/2012/03/19/let-free-style-and-streaming/

    【讨论】:

      【解决方案3】:

      在 MarkLogic 7 中,您可以使用地图构造函数递归地生成地图。我想这可能是你想要的:

      let $map := map:new( 
        (1 to 10) ! map:entry(., .)
      )
      

      或者您将map:put 作为另一个序列的一部分执行,或者在返回地图之前的return 语句中执行:

      let $map := map:map()
      let $not-useless-var := ...
      return (map:put($map, string($not-useless-var), $not-useless-var), $map)
      

      【讨论】:

      • 重点不在于地图——我只是在寻找一种在 FLWOR 中运行函数而不使用let 的方法。我更新了我的问题以澄清一点。
      • 映射是一个例外,但通常,XQuery 中的函数没有副作用,所以如果您不打算存储结果,那为什么要调用该函数呢?
      • 在 XQuery 和其他函数式语言中,一切都是表达式,因此一切都会产生一个值。即使该值是一个空序列。该语言确实没有“仅调用函数”的概念。调用函数是表达式求值。在 FLWOR 中,您需要将结果绑定到变量,这就是 FLWOR 语法。我使用 $_ 作为忽略变量的约定。
      【解决方案4】:

      在普通的 XQuery 中(忽略像 XQuery scripting extension 这样的扩展)没有副作用,因此调用函数而不使用其返回值是没有意义的。

      您可能在这里缺少的是map:put() 返回一个添加了额外项目的 地图,它确实 改变了原始地图。所以你的$useless-var其实并不是没用的。

      编辑:实际上我不确定 MarkLogic 的 map:put() 是否会改变地图。 (如果是这样,那真的很糟糕。)我在考虑建议的 XQuery 3.1 映射(我在 BaseX 中使用过),它绝对是不可变的。

      【讨论】:

      • 这并不完全正确。显然,不同的 XQuery 处理器实现映射的方式都略有不同,并且在 MarkLogic 中 map:put 确实会改变原始映射(并返回一个空序列)。
      • @wst 它甚至没有礼貌地返回同一张地图?真是太可怕了。
      • 是的,MarkLogic 映射是直接可变的。它们在服务器内部实现为 C++ 数据结构。它们是作为性能增强引入的(并且速度非常快),但确实违反了无副作用函数式编程的期望。它们是 MarkLogic 特定的,不是 XQuery 标准的一部分(并且比 XQuery 3.x 早几年)Sharp 工具。明智地使用。
      【解决方案5】:

      由于您的问题的重点是关于在不存储中间结果的情况下运行函数,您可能会发现 map 运算符 (!) 很有帮助:

      local:build-sequence() ! local:do-something-to-each(.)
      

      这对于处理序列很有用。如果您正在考虑更多地处理某事的结果,答案很可能是拥抱 XQuery 的功能性质:

      local:produce-result(
        local:build-parameter(),
        local:retrieve-config()
      )
      

      不确定您在寻找什么,但希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-11
        • 2015-10-22
        • 2019-05-12
        • 2020-04-14
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        • 2011-11-24
        相关资源
        最近更新 更多