【问题标题】:How to avoid function invocation in COMPOSE-like circumstances?如何避免在类似 COMPOSE 的情况下调用函数?
【发布时间】:2014-12-24 20:17:39
【问题描述】:

在下面的代码中,我们可以通过一个SET-WORD将GET-WORD的结果赋值给p,然后在新名称下使用:

p: :print 
p [{Hello} {World}]

但是,如果您在使用 COMPOSE 时遇到了这样的情况怎么办?

do compose [p: (:print)] 
p [{Hello} {World}]

这给出了一个错误:

*** ERROR
** Script error: -unnamed- is missing its value argument
** Where: do
** Near: do compose [p: (:print)] p ["Hello" "World"]

因此,当在解释器中看到时,就像块中的函数值是“活的”......无论它们是否作为评估结果被提取。 (看起来它们应该是惰性的,除非以某种方式获取或应用,否则在 COMPOSE 或类似内容中不可能进行此类分配。)

看来你必须引用一个get-word,例如:

do compose [p: (quote :print)] 
p [{Hello} {World}]

这可以使 p 成为打印功能。但是你可以不通过 GET-WORD 或类似的代理来做到这一点吗?

【问题讨论】:

    标签: function rebol rebol3


    【解决方案1】:

    是的,您可以“解除”活动功能!具有 DO 方言特征的值:

    >> do probe compose [p: quote (:print)]
    [p: quote make native! [[
            "Outputs a value followed by a line break."
            value [any-type!] "The value to print"
        ]]]
    
    >> p [{Hello} {World}]                  
    Hello World
    

    这里的关键是用于QUOTE单个参数的特殊参数传递模式:

    >> source quote
    quote: make function! [[
        "Returns the value passed to it without evaluation."
        :value [any-type!]
    ][
        :value
    ]]
    

    这种参数传递模式,难以想象地称为“获取参数”,它禁止对参数值进行评估。所以在我们的特殊情况下,它阻止了函数的“活动”性质!承担的价值。

    有关参数传递模式的更多详细信息,您可能需要查看最近的treatise about literal and get arguments,它比较了 Rebol 2 和 Rebol 3 之间的差异,以提供历史视角。

    【讨论】:

    • 很高兴指出。我没想过要尝试括号外的引用,这比我做的其他方式要好。虽然我的技术问题特别是我是否可以在 COMPOSE 与外部的括号内放入任何东西来解除它,所以答案(至少对于我要问的问题)是“否”。
    • 不,你当然不能。因为“武装”它的不是 COMPOSE。对于 COMPOSE,活动值与非活动值不存在区别。这只是 DO 方言的一个特性,然后您可以通过 DO 显式调用它。
    • 在我看来,您真正想要做的是将一个值拼接到一个块中,并希望该值对于 DO 方言而言是“非活动的”。在这个特定的示例中,您希望这样可以确保始终在前面的 set-word! 的上下文中分配该值。因此,要实现这一点,您必须要么 创建一个在 DO 方言中具有所需语义的构造,要么 控制周围的代码(例如通过在正确的地方,如我的回答)。
    【解决方案2】:

    使用以下方式创建 get-word,它为您购买了额外的间接级别:

    >> do compose [p: (to-get-word 'print)]
    >> p [{Hello} {World}]
    Hello World
    

    如果您希望使用 DO [...] 表单完成分配,那么您需要为匿名函数分配一个单词,以便以被动方式对其进行操作。

    另一种选择是在组合块之外进行赋值:

    p: first compose [(:print)]
    

    【讨论】:

    • 如果您希望使用 DO [...] 表单完成分配,那么是的,您需要为匿名函数分配一个单词,以便以被动方式对其进行操作。另一种选择是在组合块之外进行赋值:p: first compose [(:print)].
    【解决方案3】:

    第一个问题是你需要这个做什么?

    因为它可以在没有 compose 的情况下工作。

    Do [p: :print]
    P 1
    

    而且没有一个关键词

    Do [p: get first [print]]
    

    编辑:

    我不了解 C++ 绑定的含义,但 'compose 用于有选择地评估块的某些部分。在您的示例中,您想要评估一个部分,但仍希望它不被评估,因此您需要阻止它过早地被评估,例如:

    do compose [p1: (to get-word! 'x)] 
    

    如果你想使用 compose,而没有 get-/lit-word!,你可以尝试引用:

    do compose [p4: get quote ( quote print)]
    

    内部的'quote guards'打印在撰写期间不被评估,外部的'quote guards'在'do'期间进行,以便'get可以获取值。

    【讨论】:

    • 影响the C++ binding中函数的赋值。如果您正在撰写某些内容并希望将结果用于作业,我在这里更一般地表达了它。
    • 我仍然不确定我是否理解真正的问题,但我已经编辑了我的原始答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多