4

这是我将 cmd 作为 Rebol 指令执行的函数:

exec-cmd: func [
        cmd [ block! ] "Rebol instructions"
        /local err
] [
        if error? err: try [
                do cmd
        ] [ print mold disarm err ]
]

当我启动该功能时,我遇到了以下错误消息:

** Script Error: err needs a value
** Where: exec-cmd
** Near: if error? err: try [
    do cmd
]

如何避免此消息并管理错误?

4

2 回答 2

5

使用set/anyandget/any处理常规赋值和评估不能处理的值。

if error? set/any 'err try [
    do cmd
] [ print mold disarm get/any 'err ]

一旦错误解除,您就可以正常处理它。

于 2014-01-21T22:38:29.903 回答
5

当 Rebol 默认评估器看到一个 SET-WORD 序列时!后跟一个“完整”表达式,它将将该表达式的结果分配给命名的单词。

然而,Rebol 有能力从一个叫做 UNSET! 的函数返回一种特殊的“无”。例如:

>> type? print {What "value" does a print return?}
What "value" does a print return?
== unset!

这与返回 NONE 不同!价值...因为如果您继续评估链,评估者将不允许他们进行作业。

>> foo: print {This isn't legal}
This isn't legal
** Script Error: foo needs a value
** Near: foo: print "This isn't legal"

变量实际上不能“保存值”类型为 UNSET!。未设置!只是尝试访问未设置的变量时将获得的“值类型”。不管是否存在 none 值的哲学等价,机械结果是,如果你想允许一个 unset!要有效地“分配”价值,您必须使用set函数和/any细化来进行“分配”:

>> set/any 'foo (print {This works...})
This works...
== unset!

但是为了能够从该值中读取,您不能只引用它,因为该变量现在未定义。您需要使用相应的get

>> type? get/any 'foo
== unset!

无论如何,这就是你看到这个的背景。您cmd大概以返回 UNSET! 的函数结束,就像可能print

这是一个可能具有说明性的示例:

exec-cmd: func [
    cmd [block!] "Rebol instructions"
    /local err
] [
    set/any 'result (try [do cmd])
    case [
        unset? get/any 'result [
            print "Cmd returned no result"
        ]

        function? :result [
            print ["Cmd returned a function:" newline (mold :result)]
        ]

        ;-- Rebol3 only --
        ;
        ; closure? :result [
        ;    print ["Cmd returned a closure:" newline (mold :result)]
        ; ]

        ;-- Rebol3 should be changed to match Red and not require this --
        ;
        lit-word? :result [
            print ["Cmd returned a literal word:" newline (mold :result)]
        ]

        error? result [
            print mold disarm result
        ]

        true [
            print ["Cmd returned result of type" (mold type? result)]
            print ["The value was:" newline (mold result)]
        ]
    ]
]

请注意,一旦您已经处理了结果可能未设置的情况,您就不必使用get/any并且可以进行正常访问。

解释器的工作方式有一个基本问题,即如果一个词绑定到一个函数!值(也是 Rebol3 中的 CLOSURE! 值)然后引用该词调用相关代码。要解决这个问题,如果您知道您处于一个单词可能包含这样一个值的情况,您可以使用 GET 或 SET-WORD 的类似物!称为 GET-WORD!。这些通常被认为是“丑陋的”,因此最好将需要测试这种边缘情况的代码部分隔离开来,而不是将冒号放在不需要的东西前面!

被认为是设计缺陷的是所谓的“字词衰减”。这需要使用 GET-WORD!在 Rebol2 中,如果你手上有一个实际的字面量词。在这种情况下,你的程序不会崩溃,它只是不会给你你所期望的。 此处已解释...它已在 Red 中进行了更改,因此肯定会为 Rebol3 进行更改。

此外,在 Rebol3 中消除了错误被“武装”和需要“解除”以进行检查的概念。这不会影响error?Rebol2 中的测试,因此您需要使用 GET-WORD!,但会影响您可以使用它们执行的所有其他操作。

好的。我我已经涵盖了这里的所有案例,但如果我没有,有人会纠正我!


(注意:如果您想知道如何制作自己的返回 UNSET 的函数!就像 print 一样,只需使用exit而不是return

>> nothing: func [value] [exit]

>> type? nothing 1020
== unset!
于 2014-01-21T22:39:48.140 回答