2014-01-21 50 views
4

这里我充当雷博尔指令执行CMD:当我使用错误?和尝试,犯错需要的值

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 
] 

如何我是否可以避免此消息并管理错误?

回答

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的! 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中,如果你有一个实际字面上的单词在你的手中。在这种情况下,你的程序不会崩溃,它不会给你所期望的。 It's explained here ...它已经在Red中更改,所以肯定会更改为Rebol3。

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

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


(注意:如果你很好奇如何让自己的函数返回未设置像打印那样,只是使用的exit代替return!)

>> nothing: func [value] [exit] 

>> type? nothing 1020 
== unset! 
+0

我已经长大关于为什么你必须使用的问题:结果如果一个变量是一个点亮的词...... [CureCode票#2101](http://curecode.org/rebol3/ticket.rsp?id=2101)。真的,你应该在Rebol3中唯一需要特殊处理的东西是'unset!'和'function!'...(我认为)。 – HostileFork

5

使用set/anyget/any来处理定期赋值和评估不能的值。

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

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