diff --git a/2019-07-30_error_and_condition_handling_in_R/Error and Condition Handling in R.Rmd b/2019-07-30_error_and_condition_handling_in_R/Error and Condition Handling in R.Rmd new file mode 100644 index 0000000..0b6f3ad --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/Error and Condition Handling in R.Rmd @@ -0,0 +1,353 @@ +--- +title: "Error and Condition Handling in R" +author: "John Peach" +date: "July 30, 2019" +output: + ioslides_presentation: + css: style.css + incremental: false + logo: logo_ocrug_blue_grey.svg +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = FALSE) +``` + +## Outline + +* Built in conditions +* Controlling the output of warnings +* Checking for errors and stopping +* Capturing errors and handling them + + +## Built in conditions + +- message: + - 'simple' diagnostic messages +- warning: + - A warning message but execution continues +- stop: + - An error message that can cause execution is stop + +## Using message instead of print + +- Instead of using 'print' for debugging, use message(). +- It goes to stderr(). Better control with using sinks +```{r, eval= TRUE, echo=TRUE} +add <- function (...) { + message(paste("add:Parameters:", paste(..., collapse = ", "))) + result <- sum(...) + message(paste("add:returned:", result)) + result + invisible() +} +add(1:10) +``` + +## You can suppress the messages + +- Suppress messages instead of adding/removing print statements +```{r, eval= TRUE, echo=TRUE} +add <- function (...) { + message(paste("add:Parameters:", paste(..., collapse = ", "))) + result <- sum(...) + message(paste("add:returned:", result)) + result + invisible() +} +suppressMessages(add(1:10)) +``` + +Now you do not have to comment them out! + +## Warning messages + +- Used to advise when business logic is handling a strange situation, such as: + - using default parameters, + - type casting weirdness i.e. as.numeric("a") +- Works similar to message() but has output controls +```{r, eval= TRUE, echo=TRUE} +test <- function() { + warning("The British are coming", + call. = TRUE, # make 'call' part of the message + immediate. = TRUE) # override getOption('warn')) +} +test() +``` + +## Controlling Output: When to print + +- Output is controlled with global options + - accessor: getOption('\') + - mutator: options(\ = \) + +- \: warn + - Controls when the warnings are printed + - Allowed values: + - -1: suppress output (technically warn < 0) + - 0: printed after the top-level function has complete + - 1: printed as they occur + - 2: convert into errors (technically warn > 1) + +## Controlling Output: Message length + +- \: warning.length + - Truncates the length of each message (error and warning) + - values: 100...8170 default:1000 (long) +```{r, eval= TRUE, echo=FALSE } +OLD_warning.length = getOption('warning.length') +``` + +```{r, eval= TRUE, echo=FALSE} +msg <- paste(LETTERS[round(runif(1000, min = 1, max = 26))], collapse = "") +``` + +```{r, eval= TRUE, echo=TRUE, size = "tiny"} +options(warning.length = 100) +warning(msg) +``` + +```{r, eval= TRUE, echo=FALSE } +options(warning.length = OLD_warning.length) +rm("OLD_warning.length") +``` + +## Controlling Output: Number of messages printed + +- \: nwarning + - When warn = 0, the error and warn messages are buffered + - sets the size of the buffer. Default: 50 + +## Accessing the warnings +- If getOption('warn') == 0 then there is a buffer of warning messages +- warnings(...) prints this buffer +- Parameters "..." are passed to cat() to control output +- The buffer is a variable called last.warning +- last.warning is: + - a named list + - undocumented (subject to change) + - use it in the console but not in your scripts + - does not always exist + +## Controlling Output: Modifying the message + +- \: warning.expression + - custom code is run with each call to warning() +```{r, eval= TRUE, echo=FALSE } +OLD_warning.expression = getOption('warning.expression') +``` + +```{r, eval= TRUE, echo=TRUE} +options(warning.expression = quote(getwd())) +warning("Test") +``` + +```{r, eval= TRUE, echo=FALSE } +options(warning.expression = OLD_warning.expression) +rm("OLD_warning.expression") +``` +BUG in ioslides (?) because this code outputs the following in the console: +```{r, eval= TRUE, echo=FALSE } +getwd() +``` + +## Warning messages suppression + +- Just like messages, we can suppress the warnings +```{r, eval= TRUE, echo=TRUE} +test <- function() { + warning("The British are coming", + call. = TRUE, # make 'call' part of the message + immediate. = TRUE) # override getOption('warn')) +} +suppressWarnings(test()) +``` +- The warning is not printed + +```{r, eval= TRUE, echo=TRUE} +warnings() +``` +and it is not stored in the buffer + +## Error Messages + +- Used when there is an unrecoverable error +- By default, program execution is halted +```{r, eval=FALSE, echo=TRUE} +test <- function() { + stop("In the name of love", + call. = TRUE) # call is part of the message +} +test() +``` +\#\# Error in test() : In the name of love + +## What was the last error? + +- Forgot the details of the last error message, you can use +```{r, eval=FALSE, echo=TRUE} +geterrmessage() +``` + +\#\# Error: In the name of love + +- A string with the last error message is returned +- A \\n is appended to the error message + +## stopifnot() + +- Throw an error if any condition is FALSE +- No message is returned +```{r, eval=FALSE, echo=TRUE} +stopifnot(...) +``` +... is any number of logical R expressions which should be TRUE + +```{r, eval=FALSE, echo=TRUE} +stopifnot(A, B) +# Is short hand for +if ( any(is.na(A)) || !all(A) || any(is.na(B)) || !all(B)) stop(...) +``` +NULL is treated as TRUE + +## Example: stopifnot() + +- Generally used to check function parameters +- Wrapper function for sum that checks: + - all parameters are integer + - there must be a non-zero length vector + - there are no NULLs or NANs +```{r, eval=TRUE, echo=TRUE} +Sum <- function(...){ + stopifnot(is.integer(...), length(...) > 0, + !is.null(...), !is.nan(...)) + as.integer(sum(...)) +} +Sum(1L:10L) +``` + +## Condition System +- message(), warning(), stop() are built on the Condition System +- It is used for error handling but is more flexible than that +- Consists of three parts + - Signalling Condition + - Handling Condition + - Restarting (Advanced topic) +- The task of handling the error is split between the Handler and the Restart + +## Components + +- Signaller + - A method that raises / throws and exception object + - Creates an object derived from the S3 class 'condition' + - Language framework handles its execution path + - message(), warning() and stop() are signallers +- Handler + - Agrees to catch / process exception of specific classes + - Handles exception only from the call stack below it + - Handlers lower on the stack may capture exception + +## Exceptions - Sequence of execution + +![exception](exception.png) +## Exceptions + +- Errors are handled by: + - Exiting the failing function + - Calling function can recover or fail itself +- Primary issue is that the stack unwinds + - Recovery code must do so without the context of the failing function + +## tryCatch + +- Unwinds the call stack +```{r, eval= FALSE, echo=TRUE} +tryCatch(expression, + condition_class_1 = function(var) ..., + condition_class_2 = function(var) ..., + finally = ... +) +``` +- expression: must be a single expression, use { } +- var: is the condition object +- tryCatch returns the value of expression or one of the condition_class +- If the condition is not handled by one of the condition_class it moves up the call stack + +## tryCatch: Handler not invoked + +```{r, eval=TRUE, echo=TRUE} +`%+%` <- function(lhs, rhs) { + if (!is.integer(lhs) || !is.integer(rhs)){ + stop("parameters must be numeric") + } + lhs + rhs +} +tryCatch( { 5L %+% 4L }, + error = function(e) 0 +) +``` +- There was no error so the handler 'error' was not invoked +- tryCatch returned the value of the expression + +## tryCatch: Handler invoked + +```{r, eval=TRUE, echo=TRUE} +`%+%` <- function(lhs, rhs) { + if (!is.integer(lhs) || !is.integer(rhs)){ + stop("parameters must be numeric") + } + lhs + rhs +} +tryCatch( { 5L %+% 4 }, + error = function(e) 0 +) +``` +- stop() was called because 4 is double not integer +- tryCatch returned the value of the 'error' handler + +## tryCatch: No warning handler + +```{r, eval=TRUE, echo=TRUE} +`%+%` <- function(lhs, rhs) { + if (is.double(rhs)) { + rhs = as.integer(rhs); warning("casting rhs to integer") + } + if (!is.integer(lhs) || !is.integer(rhs)){ + stop("parameters must be numeric") + } + lhs + rhs +} +tryCatch( { 5L %+% 4 }, + error = function(e) 0 +) +``` +- Sum is computed and a warning is displayed + +## tryCatch: finally + +```{r, eval=TRUE, echo=TRUE} +tryCatch( { + text <- 'foo' + message(text) + }, + message = function(e) { + text <- paste(conditionMessage(e), 'bar') + text # This is the value returned by tryCatch. Different environment + }, + finally = { + # This block is run iff a handler is called + print(text) # handler does not alter value + } +) +``` + +## Comment on Condition System + +- I showed you how to use R like you use error systems in Java/python +- R has a much more powerful system that is based on lisp +- Code is not "rolled-up" the call stack, it can be restarted +- We can build custom conditions and handle them +- The Condition System can be used for much more than errors + + diff --git a/2019-07-30_error_and_condition_handling_in_R/Error_and_Condition_Handling_in_R.html b/2019-07-30_error_and_condition_handling_in_R/Error_and_Condition_Handling_in_R.html new file mode 100644 index 0000000..acb46d0 --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/Error_and_Condition_Handling_in_R.html @@ -0,0 +1,3597 @@ + + + + Error and Condition Handling in R + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+

+

+

July 30, 2019

+
+
+ +

Outline

+ +
    +
  • Built in conditions
  • +
  • Controlling the output of warnings
  • +
  • Checking for errors and stopping
  • +
  • Capturing errors and handling them
  • +
+ +

Built in conditions

+ +
    +
  • message: + +
      +
    • ‘simple’ diagnostic messages
    • +
  • +
  • warning: + +
      +
    • A warning message but execution continues
    • +
  • +
  • stop: + +
      +
    • An error message that can cause execution is stop
    • +
  • +
+ +

Using message instead of print

+ +
    +
  • Instead of using ‘print’ for debugging, use message().
  • +
  • It goes to stderr(). Better control with using sinks
  • +
+ +
add <- function (...) {
+   message(paste("add:Parameters:", paste(..., collapse = ", ")))
+   result <- sum(...)
+   message(paste("add:returned:", result))
+   result
+   invisible()
+}
+add(1:10)
+ +
## add:Parameters: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ +
## add:returned: 55
+ +

You can suppress the messages

+ +
    +
  • Suppress messages instead of adding/removing print statements
  • +
+ +
add <- function (...) {
+   message(paste("add:Parameters:", paste(..., collapse = ", ")))
+   result <- sum(...)
+   message(paste("add:returned:", result))
+   result
+   invisible()
+}
+suppressMessages(add(1:10))
+ +

Now you do not have to comment them out!

+ +

Warning messages

+ +
    +
  • Used to advise when business logic is handling a strange situation, such as: + +
      +
    • using default parameters,
    • +
    • type casting weirdness i.e. as.numeric(“a”)
    • +
  • +
  • Works similar to message() but has output controls
  • +
+ +
test <- function() {
+    warning("The British are coming",
+            call. = TRUE, # make 'call' part of the message
+            immediate. = TRUE) # override getOption('warn'))
+}
+test()
+ +
## Warning in test(): The British are coming
+ +

Controlling Output: When to print

+ +
    +
  • Output is controlled with global options + +
      +
    • accessor: getOption(‘<OPTION>’)
    • +
    • mutator: options(<OPTION> = <VALUE>)
    • +
  • +
  • <Option>: warn + +
      +
    • Controls when the warnings are printed
    • +
    • Allowed values: + +
        +
      • -1: suppress output (technically warn < 0)
      • +
      • 0: printed after the top-level function has complete
      • +
      • 1: printed as they occur
      • +
      • 2: convert into errors (technically warn > 1)
      • +
    • +
  • +
+ +

Controlling Output: Message length

+ +
    +
  • <Option>: warning.length + +
      +
    • Truncates the length of each message (error and warning)
    • +
    • values: 100…8170 default:1000 (long)
    • +
  • +
+ +
options(warning.length = 100)
+warning(msg)
+ +
## Warning:
+## SAISXBBULMPFRAMTTEKROXCPWHOSCINBGGHPGQKAUFGYQQAFQMCAIGUOVEWGMDMMQRMUIGVUJIXSENUSHXJOSWKYCVYNNENPNCWOWMMCICWWNDWBSPDBOHFXUFLHQHMJBEWVJWWCINUGVWKMXQTYCFRPOIKDQYGNEGJLGYWHESEJRSMFKGAFHGPBDJDOPUFOSOMGYIMVDKZKUPDMWKUJADVJUPOVHCGVYAWREZSWAUYPCEVRFXULQMBBVKADCEGEVMZLDYQJGDEMERUCMGYONWUOYOEVNLQZELURLQVESQJEXJMIMPIOPHDNTRUBVOWDVMQPOFRBXSKRJXQRVLJUVOTCXMFWFNWUVNOTSFHHMVEBEFJRXCJYDRGUKTRWKEUNFEEIHMAHRDTPRGMQYEUMNAWXHHJSHDHQHNPNMIHIRCGKVGPTJBLOJZSDHXTCSACPTBXMXUJZSCJMETLPXWYNNANSLUIFJPMPDEPCPQHMHQDYNTRVGEUMMRFIKEMTBBTQPQWUKBKBBOYGWSBXAJJRAXBOYAMFNMJGSIBELTRGGIMEFXKGXROUSWUCHBCMCNYDUJAQOTAJYHBEKCCXTJNCMZXWSPDMIWHNTFEPJPYOPTFFYAJKYLHLWQJAAAGYHKMAPWKVUSVIFTJHXVHRTZQQMYQIWYEBTWEAXFKKBZPWIHFVRLFHUHTUCQTUHIDPMPEYDHLPQJSOWJODFOJLYNRERZWBHPLUZSHVKRGPTCQDPHKBFQQNKVIIQSUBFMIZKZDCJYGSBSZOJQOCVUCEMAFCREGJKFWKLMYPSHJRZOGUHBGWIEKWKORUNOPJVYEKPLEVPIMFKTEMDXNBUANQICSRUNKDRSFQKDVQFLORKTHEGSFHSCTSAFEABBQTTGFJWDBJNUEODCDVRSFLDKOVWQUCPBAUQAOKBKOHSAYRMNQFXBRIYGGNJSSUUWPVAIHKIRGLRMRVFVRSNKKGSREVESTQPYVPPQHGVEBKLVSIZZEP
+ +

Controlling Output: Number of messages printed

+ +
    +
  • <Option>: nwarning + +
      +
    • When warn = 0, the error and warn messages are buffered
    • +
    • sets the size of the buffer. Default: 50
    • +
  • +
+ +

Accessing the warnings

+ +
    +
  • If getOption(‘warn’) == 0 then there is a buffer of warning messages
  • +
  • warnings(…) prints this buffer
  • +
  • Parameters “…” are passed to cat() to control output
  • +
  • The buffer is a variable called last.warning
  • +
  • last.warning is: + +
      +
    • a named list
    • +
    • undocumented (subject to change)
    • +
    • use it in the console but not in your scripts
    • +
    • does not always exist
    • +
  • +
+ +

Controlling Output: Modifying the message

+ +
    +
  • <Option>: warning.expression + +
      +
    • custom code is run with each call to warning()
    • +
  • +
+ +
options(warning.expression = quote(getwd()))
+warning("Test")
+ +
## Warning: Test
+ +

BUG in ioslides (?) because this code outputs the following in the console:

+ +
## [1] "/Users/jpeach/git/ocrug/presentations/2019-07-30_error_and_condition_handling_in_R"
+ +

Warning messages suppression

+ +
    +
  • Just like messages, we can suppress the warnings
  • +
+ +
test <- function() {
+    warning("The British are coming",
+            call. = TRUE, # make 'call' part of the message
+            immediate. = TRUE) # override getOption('warn'))
+}
+suppressWarnings(test())
+ +
    +
  • The warning is not printed
  • +
+ +
warnings()
+ +

and it is not stored in the buffer

+ +

Error Messages

+ +
    +
  • Used when there is an unrecoverable error
  • +
  • By default, program execution is halted
  • +
+ +
test <- function() {
+    stop("In the name of love",
+            call. = TRUE) # call is part of the message
+}
+test()
+ +

## Error in test() : In the name of love

+ +

What was the last error?

+ +
    +
  • Forgot the details of the last error message, you can use
  • +
+ +
geterrmessage()
+ +

## Error: In the name of love

+ +
    +
  • A string with the last error message is returned
  • +
  • A \n is appended to the error message
  • +
+ +

stopifnot()

+ +
    +
  • Throw an error if any condition is FALSE
  • +
  • No message is returned
  • +
+ +
stopifnot(...)
+ +

… is any number of logical R expressions which should be TRUE

+ +
stopifnot(A, B)
+# Is short hand for
+if ( any(is.na(A)) || !all(A) || any(is.na(B)) || !all(B)) stop(...)
+ +

NULL is treated as TRUE

+ +

Example: stopifnot()

+ +
    +
  • Generally used to check function parameters
  • +
  • Wrapper function for sum that checks: + +
      +
    • all parameters are integer
    • +
    • there must be a non-zero length vector
    • +
    • there are no NULLs or NANs
    • +
  • +
+ +
Sum <- function(...){
+   stopifnot(is.integer(...), length(...) > 0, 
+             !is.null(...), !is.nan(...))
+   as.integer(sum(...))
+}
+Sum(1L:10L)
+ +
## [1] 55
+ +

Condition System

+ +
    +
  • message(), warning(), stop() are built on the Condition System
  • +
  • It is used for error handling but is more flexible than that
  • +
  • Consists of three parts + +
      +
    • Signalling Condition
    • +
    • Handling Condition
    • +
    • Restarting (Advanced topic)
    • +
  • +
  • The task of handling the error is split between the Handler and the Restart
  • +
+ +

Components

+ +
    +
  • Signaller + +
      +
    • A method that raises / throws and exception object
    • +
    • Creates an object derived from the S3 class ‘condition’
    • +
    • Language framework handles its execution path
    • +
    • message(), warning() and stop() are signallers
    • +
  • +
  • Handler + +
      +
    • Agrees to catch / process exception of specific classes
    • +
    • Handles exception only from the call stack below it
    • +
    • Handlers lower on the stack may capture exception
    • +
  • +
+ +

Exceptions - Sequence of execution

+ +

## Exceptions

+ +
    +
  • Errors are handled by: + +
      +
    • Exiting the failing function
    • +
    • Calling function can recover or fail itself
    • +
  • +
  • Primary issue is that the stack unwinds + +
      +
    • Recovery code must do so without the context of the failing function
    • +
  • +
+ +

tryCatch

+ +
    +
  • Unwinds the call stack
  • +
+ +
tryCatch(expression, 
+  condition_class_1 = function(var) ...,
+  condition_class_2 = function(var) ...,
+  finally = ...
+)
+ +
    +
  • expression: must be a single expression, use { }
  • +
  • var: is the condition object
  • +
  • tryCatch returns the value of expression or one of the condition_class
  • +
  • If the condition is not handled by one of the condition_class it moves up the call stack
  • +
+ +

tryCatch: Handler not invoked

+ +
`%+%` <- function(lhs, rhs) {
+   if (!is.integer(lhs) || !is.integer(rhs)){
+      stop("parameters must be numeric")
+   }
+   lhs + rhs
+}
+tryCatch( { 5L %+% 4L },
+   error = function(e) 0
+)
+ +
## [1] 9
+ +
    +
  • There was no error so the handler ‘error’ was not invoked
  • +
  • tryCatch returned the value of the expression
  • +
+ +

tryCatch: Handler invoked

+ +
`%+%` <- function(lhs, rhs) {
+   if (!is.integer(lhs) || !is.integer(rhs)){
+      stop("parameters must be numeric")
+   }
+   lhs + rhs
+}
+tryCatch( { 5L %+% 4 },
+   error = function(e) 0
+)
+ +
## [1] 0
+ +
    +
  • stop() was called because 4 is double not integer
  • +
  • tryCatch returned the value of the ‘error’ handler
  • +
+ +

tryCatch: No warning handler

+ +
`%+%` <- function(lhs, rhs) {
+   if (is.double(rhs)) {
+      rhs = as.integer(rhs); warning("casting rhs to integer")
+   }
+   if (!is.integer(lhs) || !is.integer(rhs)){
+      stop("parameters must be numeric")
+   }
+   lhs + rhs
+}
+tryCatch( { 5L %+% 4 },
+   error = function(e) 0
+)
+ +
## Warning in 5L %+% 4: casting rhs to integer
+ +
## [1] 9
+ +
    +
  • Sum is computed and a warning is displayed
  • +
+ +

tryCatch: finally

+ +
tryCatch( { 
+   text <- 'foo' 
+   message(text)
+   },
+   message = function(e) { 
+      text <- paste(conditionMessage(e), 'bar')
+      text # This is the value returned by tryCatch. Different environment
+      },
+   finally = {
+      # This block is run iff a handler is called
+      print(text) # handler does not alter value
+   }
+)
+ +
## [1] "foo"
+ +
## [1] "foo\n bar"
+ +

Comment on Condition System

+ +
    +
  • I showed you how to use R like you use error systems in Java/python
  • +
  • R has a much more powerful system that is based on lisp
  • +
  • Code is not “rolled-up” the call stack, it can be restarted
  • +
  • We can build custom conditions and handle them
  • +
  • The Condition System can be used for much more than errors
  • +
+ + + + +
+ + + + + + + + + diff --git a/2019-07-30_error_and_condition_handling_in_R/LICENSE.md b/2019-07-30_error_and_condition_handling_in_R/LICENSE.md new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/2019-07-30_error_and_condition_handling_in_R/README.md b/2019-07-30_error_and_condition_handling_in_R/README.md new file mode 100644 index 0000000..7c769ec --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/README.md @@ -0,0 +1,15 @@ +# Error and Condition Handling in R + +* 2017-01-26 +* Speaker: John Peach + +## Abstract + +Being an interactive language, it is common to not perform a lot of error checking in R. Even popular packages lack often lack the robustness seen in similar tools in other languages. This may be in part due to the background of R developers, the environments where R scripts are used, cultural norms or because the error handling system in R is a little different. Generally, a language handles errors in one of three ways. A function returns a special value on an error (i.e. C, bash) or it throws an exception that unwinds the call stack where the error is dealt with in a different scope (i.e. Java, python). The approach used in R is based on Lisp. In general, errors are handled by a 'condition system' that is powerful and flexible. + +The condition system in R is quite powerful and is designed to deal with sending signals from one part of the call stack to another. These signals can be errors or any other type of message that is desired. It consists of three components, a 'signal' is sent from the executing code, control is transferred to the 'handler' code that handles the signal. Then a 'restart' can be executed. This is in some ways similar to the throw-catch mechanisms in other languages. However, these languages require that the call stack is unwound and the handling of the error is in a different context than where the error occurred. In R, the condition system allows this behavior to be mocked but it also allows the condition to be handled in the context of the code that generated the signal. + +So, what does this mean? It means that we can write code that generates and error at a low level but it is the higher level code that determines how the error is dealt. The system then restarts as if the error did not occur. Put another way, a function can be written such that it abstracts the fixing of errors to higher level code but the fix operates as if it was part of the lower level code. + +I will go over how you can write defensive code using the error handling system in R and will also give examples. The condition system for more than error management. We can see how you can write a general purpose tool that does not know how to fix problems and them wrap that in business logic for a specific application. + diff --git a/2019-07-30_error_and_condition_handling_in_R/exception.png b/2019-07-30_error_and_condition_handling_in_R/exception.png new file mode 100644 index 0000000..7f49d67 Binary files /dev/null and b/2019-07-30_error_and_condition_handling_in_R/exception.png differ diff --git a/2019-07-30_error_and_condition_handling_in_R/logo_ocrug_blue_grey.svg b/2019-07-30_error_and_condition_handling_in_R/logo_ocrug_blue_grey.svg new file mode 100644 index 0000000..9373d03 --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/logo_ocrug_blue_grey.svg @@ -0,0 +1 @@ +ocrug blue \ No newline at end of file diff --git a/2019-07-30_error_and_condition_handling_in_R/style.css b/2019-07-30_error_and_condition_handling_in_R/style.css new file mode 100644 index 0000000..e79894e --- /dev/null +++ b/2019-07-30_error_and_condition_handling_in_R/style.css @@ -0,0 +1,3 @@ +.tiny { + font-size: 0.2em; +} diff --git a/README.md b/README.md index 5f01b63..c4f856a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Presentation materials from our monthly meetings --- ## 2019 ## +* 07/30/2019: *John Peach*, [Error and Condition Handling in R](https://github.com/ocrug/presentations/tree/master/2019-07-30_error_and_condition_handling_in_R/) * 06/25/2019: *Emil Hvitfeltdt*, [Making an R package with use this](https://github.com/ocrug/presentations/tree/master/2019-06-25_Making_an_R_Package_with_usethis)