Error handling 当我使用错误时?试一下,err需要一个值

Error handling 当我使用错误时?试一下,err需要一个值,error-handling,rebol,unset,rebol2,Error Handling,Rebol,Unset,Rebol2,下面是我的函数,它将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 val

下面是我的函数,它将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
]

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

使用
set/any
get/any
处理常规赋值和求值无法处理的值

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

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

当Rebol默认计算器看到一系列设置字时!后跟一个“complete”表达式,它会将该表达式的结果指定给指定的单词

但是,Rebol能够从一个名为UNSET!的函数返回一种特殊类型的“nothing”!。例如:

>> type? print {What "value" does a print return?}
What "value" does a print return?
== unset!
这与返回“无”不同!价值…因为如果你继续评估链,评估者将不允许他们参与作业

>> foo: print {This isn't legal}
This isn't legal
** Script Error: foo needs a value
** Near: foo: print "This isn't legal"
变量实际上不能“保存UNSET!”类型的值!。不安!如果您尝试访问一个未设置的变量,将得到“值类型”。不管是否存在无值的哲学等价性如何,机械的结果是,如果你想允许一个未设置的值!要有效地“分配”值,您必须使用
set
功能和
/any
优化执行该“分配”:

>> set/any 'foo (print {This works...})
This works...
== unset!
但是为了能够读取该值,您不能仅仅引用它,因为变量现在尚未定义。您需要使用相应的
get

>> type? get/any 'foo
== unset!
不管怎么说,这就是你看到这一切的背景。您的
cmd
可能以返回UNSET!的函数结束!,比如说打印

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

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!在Rebol2中,如果您手中有一个实际的文字。在这种情况下,你的程序不会崩溃,它不会给你你想要的。。。它已被更改为红色,因此肯定会更改为Rebol3

此外,Rebol3中还消除了“防护”错误和需要“防护”以进行检查的概念。这不会影响Rebol2中的
错误?
测试,因此您需要使用GET-WORD!,但是你能用它们做的一切都受到了影响

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


(注意:如果您想知道如何创建自己的函数来像print一样返回未设置的!只需使用
exit
而不是
return


我提出了一个问题,为什么必须使用:result如果变量是lit单词。实际上,在Rebol3中,您只需要处理
unset
功能…(我想)。
>> nothing: func [value] [exit]

>> type? nothing 1020
== unset!