Here we describe just one possible strategy for catching errors in R TclTk applications and displaying them in
message boxes. If using R TclTk in Windows, one quickly notices that the RGui main window frequently "gets in the
way", as R TclTk windows like to hide behind it. It therefore becomes convenient to bypass RGui altogether and just
use a batch file to run Rterm with your R TclTk code. Rather than searching for errors in a .Rout file,
it is nicer to see errors pop up as you are running the application.
We define a Try function which tries to evaluate an R expression. If the expression evaluates
succesfully, then the expected result is returned. If the expression causes an error, then this error is
displayed in a message box.
Try <- function(expr)
{
if (data.class(result<-try(expr,TRUE))=="try-error")
tkmessageBox(title="An error has occured!",message=as.character(result),icon="error",type="ok")
else
return (result)
}
Try(x <- 5)
[1] 5
Try(tkmessageBox("Hello, world!\n"))
We got an error because we should have used:
tkmessageBox(message="Hello, world!\n")
Note that if you want to apply Try to more than one expression at once, you must enclose the expressions within
braces.
This error shown above is useful, but we are not interested in reading the first part of the error message for every
single "Tcl" error, so we will define a special case of the Try function for TclTk commands. Apologies for
not using a more standard method of string-searching within R (perhaps using regular expressions), but I
have found the "[tcl]" part of the error message using a C-style string searching function,
strstr. R code for this function can be found here.
TryTcl <- function(expr)
{
if (data.class(result<-try(expr,TRUE))=="try-error")
{
errorMessage <- strstr(as.character(result),"[tcl]")
tkmessageBox(title="An error has occured!",message=errorMessage,icon="error",type="ok")
}
else
return (result)
}
TryTcl(tkmessageBox("Hello, world!\n"))
Below is a function which can be used to try to load a package. If the package cannot be found, an error is displayed in a message box.
Require <- function(pkg)
{
if (data.class(result<-try(.find.package(pkg),TRUE))=="try-error")
{
tkmessageBox(title="An error has occured!",message=paste("Cannot find package \"",pkg,"\"",sep=""),icon="error",type="ok")
return (FALSE)
}
else
{
require(pkg,character.only=TRUE)
return (TRUE)
}
}
Require("base")
[1] TRUE
Require("AnotherPackage")
[1] FALSE
Below is a function which can be used to try to load/require a Tcl package. If the package cannot be found, an error is displayed in a message box.
TclRequire <- function(tclPkg)
{
if ((data.class(result<-try(tclRequire(tclPkg),TRUE))=="try-error") || (is.logical(result) && result==FALSE))
{
tkmessageBox(title="An error has occured!",message=paste("Cannot find Tcl package \"", tclPkg,
"\". To access Tcl/Tk extensions, you must have Tcl/Tk installed on your computer, not just ",
"the minimal Tcl/Tk installation which comes with R. If you do have the full Tcl/Tk installed, make ",
"sure that R can find the path to the Tcl library, e.g. C:\\Tcl\\lib (on Windows) or ",
"/usr/local/ActiveTcl/lib (on Linux/Unix) or /Library/Tcl on Mac OSX. To tell R where to ",
"find the Tcl library, use addTclPath(\"<path to Tcl library>\").\n\n",
"If using Windows, be sure to read the R for windows FAQ at http://www.stats.ox.ac.uk/pub/R/rw-FAQ.html\n\n",
"Make sure you have the TCL_LIBRARY environment variable set to the appropriate path, e.g.",
"C:\\Tcl\\lib\\tcl8.4 and the MY_TCLTK environment variable set to a non-empty string, e.g. \"Yes\".\n\n",
"The ActiveTcl website is at http://www.activestate.com/Products/ActiveTcl/\n\n",
"The R Project website is at http://www.r-project.org\n\n",
"If you need further instructions, please contact your system administrator and consider emailing ",
"activetcl@listserv.ActiveState.com (for Tcl/Tk help) or r-help@stat.math.ethz.ch (for R help) ",
"or try browsing through the Help Mailing List archives for a similar question asked previously.",
sep=""),icon="error",type="ok")
return(FALSE)
}
else
return(TRUE)
}
TclRequire("Tktable")
[1] TRUE
TclRequire("foo")
[1] FALSE