Conditions

Mini-Lecture 11

Ben Baumer

Smith College

2024-10-24

Dragons

The ~

I can’t really grasp what the ~ means. I understand the concept of the .x and .f more than the ~.

  • ~ is just a signifier
  • Are you calling a function? Or writing an expression?

The search path

I am confused about the package environment and how they are related when doing search path. Is it a one line relationship starting from global environment to empty environment?

  • Yes.
  • It’s a path, not a tree

Order of packages

I’m unsure why tidyverse loads in the order it does. Does it have to do with dependencies between some of the packages in the tidyverse?

  • I’m not sure either, but…
  • …yes, I think it has to do with dependencies and functions that mask other functions
  • let’s check!

“Load” vs. attach

rlang is one of the imports of the purrr package, so I think rlang is automatically loaded before purrr when you load the tidyverse first, which would explain why the objects from the tidyverse are still masking those from rlang (since either way, rlang is loaded first)

  • rlang is a dependency of purrr (Imports field in DESCRIPTION)…
  • …but library(purrr) does NOT attach rlang!
  • purrr is a dependency of tidyverse (Imports field in DESCRIPTION)…
  • tidyverse attaches purrr, but NOT rlang
  • This behavior is unusual

Why multiple environments

Why does R need multiple environments? Why can’t the same environment be available to users and developers?

  • Because otherwise a user’s behavior could affect the way a developer’s code works

Inheritance

Are functions “inherited” from parent environments?

  • No. 

Are other things inherited?

  • Not exactly, but sort of…

  • …S3 objects can have multiple classes

Do most environments have just one parent (excluding the empty environment)?

  • Yes, they all do.

Advice

Common feedback from years past

  • Use message() instead of print()
  • Return data, don’t just print messages to console
  • Think in terms of vectors and data frames, not messages or single values
  • Build your function to be vectorized!
  • Code style matters: pay attention to spaces, line breaks, indents, etc.
    • Use Crtl-I
  • Why do you love for loops so much?!?!??!?!!

Conditions

Two important concepts

Three types of conditions:

  • errors
  • warnings
  • messages

(Recall R Markdown chunk options!)

Catching errors:

  • catching errors with tryCatch()

Errors

  • stop() (or rlang::abort())

  • Terminates execution immediately

my_filter <- function(x, ...) {
  if (!"wacky" %in% class(x)) {
    stop("x is not wacky")
  } 
  dplyr::filter(x, ...)
}
class(starwars) <- c("wacky", class(starwars))
my_filter(starwars, name == "Chewbacca")
# A tibble: 1 × 14
  name      height  mass hair_color skin_color eye_color birth_year sex   gender
  <chr>      <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
1 Chewbacca    228   112 brown      unknown    blue             200 male  mascu…
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>
my_filter(dplyr::starwars)
Error in my_filter(dplyr::starwars): x is not wacky

Warnings

  • warning() (or rlang::warn())
  • Execution continues
my_filter <- function(x, ...) {
  if (!"wacky" %in% class(x)) {
    warning("x is not wacky")
  } 
  dplyr::filter(x, ...)
}

my_filter(dplyr::starwars)
Warning in my_filter(dplyr::starwars): x is not wacky
# A tibble: 87 × 14
   name     height  mass hair_color skin_color eye_color birth_year sex   gender
   <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
 1 Luke Sk…    172    77 blond      fair       blue            19   male  mascu…
 2 C-3PO       167    75 <NA>       gold       yellow         112   none  mascu…
 3 R2-D2        96    32 <NA>       white, bl… red             33   none  mascu…
 4 Darth V…    202   136 none       white      yellow          41.9 male  mascu…
 5 Leia Or…    150    49 brown      light      brown           19   fema… femin…
 6 Owen La…    178   120 brown, gr… light      blue            52   male  mascu…
 7 Beru Wh…    165    75 brown      light      blue            47   fema… femin…
 8 R5-D4        97    32 <NA>       white, red red             NA   none  mascu…
 9 Biggs D…    183    84 black      light      brown           24   male  mascu…
10 Obi-Wan…    182    77 auburn, w… fair       blue-gray       57   male  mascu…
# ℹ 77 more rows
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

Messages

  • message() (don’t use print() or cat())
my_filter <- function(x, ...) {
  if (!"wacky" %in% class(x)) {
    message("x is not wacky")
  } 
  dplyr::filter(x, ...)
}

my_filter(dplyr::starwars)
x is not wacky
# A tibble: 87 × 14
   name     height  mass hair_color skin_color eye_color birth_year sex   gender
   <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
 1 Luke Sk…    172    77 blond      fair       blue            19   male  mascu…
 2 C-3PO       167    75 <NA>       gold       yellow         112   none  mascu…
 3 R2-D2        96    32 <NA>       white, bl… red             33   none  mascu…
 4 Darth V…    202   136 none       white      yellow          41.9 male  mascu…
 5 Leia Or…    150    49 brown      light      brown           19   fema… femin…
 6 Owen La…    178   120 brown, gr… light      blue            52   male  mascu…
 7 Beru Wh…    165    75 brown      light      blue            47   fema… femin…
 8 R5-D4        97    32 <NA>       white, red red             NA   none  mascu…
 9 Biggs D…    183    84 black      light      brown           24   male  mascu…
10 Obi-Wan…    182    77 auburn, w… fair       blue-gray       57   male  mascu…
# ℹ 77 more rows
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

Catching errors

add_safe <- function(x, y) {
  out <- tryCatch(
    # named function!
    error = function(cnd) {
      # stuff to do when error occurs
      x
    },
    # what you are actually trying to do
    x + y
  )
  return(out)
}

add_safe(3, 5)
[1] 8
add_safe(4, "a")
[1] 4

Now

Work on