当我使用错误?并尝试,错误需要一个价值

gwa*_*o59 4 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 ]
]
Run Code Online (Sandbox Code Playgroud)

当我启动该函数时,我遇到以下错误消息:

** Script Error: err needs a value
** Where: exec-cmd
** Near: if error? err: try [
    do cmd
]
Run Code Online (Sandbox Code Playgroud)

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

Bri*_*anH 5

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

if error? set/any 'err try [
    do cmd
] [ print mold disarm get/any 'err ]
Run Code Online (Sandbox Code Playgroud)

一旦错误撤防,您可以正常处理.


Hos*_*ork 5

当Rebol默认评估程序看到SET-WORD的序列时!后跟一个"完整"表达式,它将该表达式的结果赋值给指定的单词.

但是,Rebol能够从一个名为UNSET的函数中返回一种特殊的"无".例如:

>> type? print {What "value" does a print return?}
What "value" does a print return?
== unset!
Run Code Online (Sandbox Code Playgroud)

这与返回NONE不同!value ...因为如果你继续评估链,评估者将不允许他们进行任务.

>> foo: print {This isn't legal}
This isn't legal
** Script Error: foo needs a value
** Near: foo: print "This isn't legal"
Run Code Online (Sandbox Code Playgroud)

变量实际上不能"保持UNSET类型的值".UNSET!只是您尝试访问未设置的变量时将获得的"值类型".无论是否存在无价值的哲学等价,机械后果是如果你想允许未设置!有效地"分配"的价值你必须使用set函数和/any细化做"分配" :

>> set/any 'foo (print {This works...})
This works...
== unset!
Run Code Online (Sandbox Code Playgroud)

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

>> type? get/any 'foo
== unset!
Run Code Online (Sandbox Code Playgroud)

无论如何,这就是为什么你会看到这个的背景.您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)]
        ]
    ]
]
Run Code Online (Sandbox Code Playgroud)

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

解释器的工作方式存在一个基本问题,即如果一个单词被绑定到一个FUNCTION!value(也是Rebol3中的CLOSURE!值)然后引用该单词调用相关代码.要解决这个问题,如果你知道你的某个单词可能具有这样的值,你可以使用GET或SET-WORD的类似物!被称为GET-WORD!这些通常被认为是"丑陋的"所以最好是你可以隔离需要测试这种边缘情况的代码部分,而不是把冒号放在你不需要的东西前面!

被认为是设计缺陷的东西被称为"点亮字衰变".这需要使用GET-WORD!在Rebol2中,如果你手中有一个实际的字面词.在这种情况下,你的程序不会崩溃,它只是不会给你你期望的. 这里解释了 ......它已经在Red中更改了所以它肯定会改为Rebol3.

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

行.我我已经涵盖了所有的案例,但如果我没有,有人会纠正我!


(注意:如果你好奇如何使自己的函数返回UNSET!就像打印一样,只需使用exit而不是return)

>> nothing: func [value] [exit]

>> type? nothing 1020
== unset!
Run Code Online (Sandbox Code Playgroud)