翻翻过去那场雪
该功能trycatch()相当简单,并且有很多很好的教程。在Hadley Wickham的书Advanced-R中可以找到R中错误处理的出色解释,其后的内容是一个非常基本的介绍,withCallingHandlers()并且withRestarts()用尽可能少的词:假设低级程序员编写了一个函数来计算绝对值。他不确定如何计算,但知道如何构造错误并努力传达自己的天真:low_level_ABS <- function(x){ if(x<0){ #construct an error negative_value_error <- structure( # with class `negative_value` class = c("negative_value","error", "condition"), list(message = "Not Sure what to with a negative value", call = sys.call(), # and include the offending parameter in the error object x=x)) # raise the error stop(negative_value_error) } cat("Returning from low_level_ABS()\n") return(x)}一个中级程序员还编写了一个函数,使用可悲的不完整low_level_ABS函数来计算绝对值。他知道,negative_value 当的值为x负时,低级代码将引发错误,并通过建立允许用户控制错误恢复(或不恢复)的方式来建议解决问题的方法。restartmid_level_ABSmid_level_ABSnegative_valuemid_level_ABS <- function(y){ abs_y <- withRestarts(low_level_ABS(y), # establish a restart called 'negative_value' # which returns the negative of it's argument negative_value_restart=function(z){-z}) cat("Returning from mid_level_ABS()\n") return(abs_y)}最终,高级程序员使用该mid_level_ABS函数来计算绝对值,并建立条件处理程序,该条件处理程序通过使用重新启动处理程序来告诉 错误mid_level_ABS从negative_value错误中恢复。high_level_ABS <- function(z){ abs_z <- withCallingHandlers( # call this function mid_level_ABS(z) , # and if an `error` occurres error = function(err){ # and the `error` is a `negative_value` error if(inherits(err,"negative_value")){ # invoke the restart called 'negative_value_restart' invokeRestart('negative_value_restart', # and invoke it with this parameter err$x) }else{ # otherwise re-raise the error stop(err) } }) cat("Returning from high_level_ABS()\n") return(abs_z)}所有这些的要点是,通过使用withRestarts()and withCallingHandlers(),该函数 high_level_ABS能够告诉您mid_level_ABS如何从错误引起的low_level_ABS错误中恢复而不会停止执行 mid_level_ABS,这是您无法做到的tryCatch():> high_level_ABS(3)Returning from low_level_ABS()Returning from mid_level_ABS()Returning from high_level_ABS()[1] 3> high_level_ABS(-3)Returning from mid_level_ABS()Returning from high_level_ABS()[1] 3在实践中,low_level_ABS代表一个mid_level_ABS调用很多(甚至可能数百万次)的函数,针对错误的正确处理方法可能会因情况而异,如何处理特定错误的选择留给了更高级别的函数(high_level_ABS)。