【问题标题】:When I use error? and try, err need a value当我使用错误?并尝试,错误需要一个值
【发布时间】:2014-02-11 16:00:31
【问题描述】:

这是我将 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
]

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

【问题讨论】:

    标签: error-handling rebol unset rebol2


    【解决方案1】:

    当 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 并且可以进行正常访问。

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

    被视为设计缺陷的是所谓的“字词衰减”。这需要使用 GET-WORD!在 Rebol2 中,如果你手上有一个 actual 字面量词。在这种情况下,你的程序不会崩溃,它只是不会给你你所期望的。 It's explained here...已经改成红色,所以肯定会改成 Rebol3。

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

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


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

    >> nothing: func [value] [exit]
    
    >> type? nothing 1020
    == unset!
    

    【讨论】:

    • 我已经提出了一个问题:如果变量是亮字,为什么必须使用 :result...CureCode Ticket #2101。在 Rebol3 中,您真正应该 必须处理特殊情况的唯一事情是 unset!function!...(我认为)。
    【解决方案2】:

    使用set/anyget/any 处理常规赋值和评估无法处理的值。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 2014-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      相关资源
      最近更新 更多