[RkWard-devel] Usage of try() statements

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Wed Mar 21 22:42:48 UTC 2007


Hi all,

this is nothing to deal with for 0.4.7, but I think we should address this 
soon after. If you don't have the time to look at it right now, no problem, 
but maybe you could provide some feedback on this, eventually:

We're currently using try() statements in two main situations:

1) When plotting. The reason we use try(), here, is that we need to make sure 
to close the graphing device, even if the plot itself fails. As in:
	rk.graph.on()
	try ({
		plot ("a")		# this will fail
	})
	rk.graph.off()
If we did not do this, the device would stay open, potentially causing 
substantial confusion.

2) When dealing with many options or many variables (or both at once), like 
e.g. in the descriptive statistics plugin. Roughly:
	for ([iterate over a list of objects]) {
		try (result[index, name] <- some.calculation())
		try (result[index, name] <- some.other.calculation())
		[or]
		try ({
			result[index, name] <- some.calculation()
			result[index, name] <- some.other.calculation()
		})
	}
Here, the idea is that it is probably a good thing, if a failure on a single 
object/function does not stop the entire calculation. So for that 
object/function, you'd simply get an NA, and everything else would still be 
calculated.

So far so good, but there is a drawback: Errors are suppressed entirely, and 
the error message will never be shown. While R error messages are often hard 
to decipher, getting no message at all, just a missing result, is certainly 
worse. So I think it would be good to add error messages back in.

How to do this? Some thoughts, better solutions may be available. I'm 
providing separate ideas for 1 and 2, as I think these problems may need 
differen approaches:
1a) use
	rk.graph.on()
	tryCatch({
		plot ("a")
	}, error=warning)
	rk.graph.off()
This will convert the error into a warning. So the error will be shown in some 
form, and rk.graph.off() will still be called - unless the user has set:
	options (warn=2)

1b) use
	rk.graph.on()
	tryCatch({
		plot ("a")
	}, finally=rk.graph.off())
The error will stay an error, but rk.graph.off() is sure to be called. One 
problem is that this will be a slight mess, when making sure that ", 
finally=rk.graph.off()" is only added, if this is not a plot preview. On the 
other hand, we can probably live with that (and in fact, we could omit the 
entire tryCatch() statement for previews).

1c) use
	rk.graph.on()
	on.exit(rk.graph.off())
	plot ("a")
This will make sure rk.graph.off() is called as soon as leaving the "local()" 
function. The drawbacks are that the commands are written out of sequence, 
making it harder to understand, and this will not work on top level, i.e. if 
the user copies the command without the local().

I lean towards 1b at the moment.

2a) Using
	result[index, name] <- try (some.calculation())
will in most cases place the error message in the appropriate column. Problems 
are: The error message is actually a list, and placing it into the result may 
not always work. Typically the result is numeric. If we place an error 
message in there, it becomes a character column, which may preclude some 
usages of the result. It does not lend itself well to cases, where 
some.calculation() actually produces several results that should go into 
separate columns. Finally, it means each single function needs to be wrapped 
into a try statement, and we can not place several functions inside a try({}) 
block.

2b) use
	for (...) {
		results[index, 'error'] <- tryCatch ({
			result[index, name] <- something()
				...
			NA
		}, error=function (e) e$message)
	}
	if (all (is.na (results[['error']])) results[['error']] <- NULL
This adds a column "error". Errors will go in there, leaving other columns 
intact. If there have been no errors, the error column is removed at the end. 
The main drawback is, that this is fairly complex.

2c) use
	tryCatch ({
			result[index, name] <- something()
			...
	}, error=warning)
this is similar to 1a. Errors will be converted to be warnings. It is somewhat 
less complex than 2b, and in this use case, if the user has set
	options(warn=2)
this would still be relatively benign, as the calculation will be aborted, but 
the app will remain in a reasonable state, without any device open. The main 
drawback is, that it will not be quite as easy to see where the warnings that 
are generated really "belong", i.e. for which object they have been 
generated. Also, currently warnings from plugins are only shown in a dialog ( 
but it should be feasible to add them to the output instead / additionally).

I don't have a clear preference for any of 2, so far.

Comments / ideas?

Regards
Thomas




More information about the Rkward-devel mailing list