31 Exceptions and debugging

31.1 Condition handling

  1. Q: Compare the following two implementations of message2error(). What is the main advantage of withCallingHandlers() in this scenario? (Hint: look carefully at the traceback.)


31.2 Defensive programming

  1. Q: The goal of the col_means() function defined below is to compute the means of all numeric columns in a data frame.

    However, the function is not robust to unusual inputs. Look at the following results, decide which ones are incorrect, and modify col_means() to be more robust. (Hint: there are two function calls in col_means() that are particularly prone to problems.)

    A: We divide the tests according their input types and look at the results:

    We can make the following changes:

    And look at the tests again:

    For faster failing in the error cases (where the input is not a data.frame), we can add stopifnot(is.data.frame(df)) in the first line of col_means().

  2. Q: The following function “lags” a vector, returning a version of x that is n values behind the original. Improve the function so that it (1) returns a useful error message if n is not a vector, and (2) has reasonable behaviour when n is 0 or longer than x.

    A: First we test lag()’s actual bahaviour:

    We can adjust lag(), to get better bahaviour in the latter two error cases:

    Now we look again at the tests:

    Note that we didn’t test/specify lag()’s behaviour for negative, decimal or length(n) != 1 inputs of n.