bookclub-advr

DSLC Advanced R Book Club
git clone https://git.eamoncaddigan.net/bookclub-advr.git
Log | Files | Refs | README | LICENSE

html.json (34548B)


      1 {
      2   "hash": "29629fbcf0e368d59b034407d4b9669c",
      3   "result": {
      4     "engine": "knitr",
      5     "markdown": "---\nengine: knitr\ntitle: Quasiquotation\n---\n\n## Learning objectives:\n\n- What quasiquotation means\n- Why it's important\n- Learn some practical uses\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(rlang)\nlibrary(purrr)\n```\n:::\n\n\n## Introduction\n\nThree pillars of *tidy* evaluation\n\n   1. Quasiquotation\n   2. Quosures (chapter 20)\n   3. Data masks (Chapter 20)\n\n**Quasiquotation = quotation + unquotation**\n\n- **Quote.** Capture unevaluated expression... (\"defuse\")  \n- **Unquote.** Evaluate selections of quoted expression! (\"inject\")\n- Functions that use these features are said to use Non-standard evaluation (NSE)\n- Note: related to Lisp macros, and also exists in other languages with Lisp heritage, e.g. Julia\n\n> On it's own, Quasiquotation good for programming, but combined with other tools, \n> important for data analysis.\n\n## Motivation\n\nSimple *concrete* example:\n\n`cement()` is a function that works like `paste()` but doesn't need need quotes\n\n(Think of automatically adding 'quotes' to the arguments)\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncement <- function(...) {\n  args <- ensyms(...)\n  paste(purrr::map(args, as_string), collapse = \" \")\n}\n\ncement(Good, morning, Hadley)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] \"Good morning Hadley\"\n```\n\n\n:::\n:::\n\n\nWhat if we wanted to use variables? What is an object and what should be quoted?\n\nThis is where 'unquoting' comes in!\n\n\n::: {.cell}\n\n```{.r .cell-code}\nname <- \"Bob\"\ncement(Good, afternoon, !!name) # Bang-bang!\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] \"Good afternoon Bob\"\n```\n\n\n:::\n:::\n\n\n## Vocabulary {-}\n\nCan think of `cement()` and `paste()` as being 'mirror-images' of each other.\n\n- `paste()` - define what to quote - **Evaluates** arguments\n- `cement()` - define what to unquote - **Quotes** arguments\n\n**Quoting function** similar to, but more precise than, **Non-standard evaluation (NSE)**\n\n- Tidyverse functions - e.g., `dplyr::mutate()`, `tidyr::pivot_longer()`\n- Base functions - e.g., `library()`, `subset()`, `with()`\n\n**Quoting function** arguments cannot be evaluated outside of function:\n\n::: {.cell}\n\n```{.r .cell-code}\ncement(Good, afternoon, Cohort) # No problem\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] \"Good afternoon Cohort\"\n```\n\n\n:::\n\n```{.r .cell-code}\nGood      # Error!\n```\n\n::: {.cell-output .cell-output-error}\n\n```\n#> Error: object 'Good' not found\n```\n\n\n:::\n:::\n\n\n**Non-quoting (standard) function** arguments can be evaluated:\n\n::: {.cell}\n\n```{.r .cell-code}\npaste(\"Good\", \"afternoon\", \"Cohort\")\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] \"Good afternoon Cohort\"\n```\n\n\n:::\n\n```{.r .cell-code}\n\"Good\"\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] \"Good\"\n```\n\n\n:::\n:::\n\n\n\n## Quoting\n\n**Capture expressions without evaluating them**\n\n\n::: {.cell}\n::: {.cell-output .cell-output-stderr}\n\n```\n#> Warning in body[[col]][rows][!is.na(result)] <- omit_na(result): number of\n#> items to replace is not a multiple of replacement length\n```\n\n\n:::\n\n::: {.cell-output-display}\n\n```{=html}\n<div id=\"daqhfwlbgd\" style=\"padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;\">\n<style>#daqhfwlbgd table {\n  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n#daqhfwlbgd thead, #daqhfwlbgd tbody, #daqhfwlbgd tfoot, #daqhfwlbgd tr, #daqhfwlbgd td, #daqhfwlbgd th {\n  border-style: none;\n}\n\n#daqhfwlbgd p {\n  margin: 0;\n  padding: 0;\n}\n\n#daqhfwlbgd .gt_table {\n  display: table;\n  border-collapse: collapse;\n  line-height: normal;\n  margin-left: auto;\n  margin-right: auto;\n  color: #333333;\n  font-size: 16px;\n  font-weight: normal;\n  font-style: normal;\n  background-color: #FFFFFF;\n  width: auto;\n  border-top-style: solid;\n  border-top-width: 2px;\n  border-top-color: #A8A8A8;\n  border-right-style: none;\n  border-right-width: 2px;\n  border-right-color: #D3D3D3;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #A8A8A8;\n  border-left-style: none;\n  border-left-width: 2px;\n  border-left-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_caption {\n  padding-top: 4px;\n  padding-bottom: 4px;\n}\n\n#daqhfwlbgd .gt_title {\n  color: #333333;\n  font-size: 125%;\n  font-weight: initial;\n  padding-top: 4px;\n  padding-bottom: 4px;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-bottom-color: #FFFFFF;\n  border-bottom-width: 0;\n}\n\n#daqhfwlbgd .gt_subtitle {\n  color: #333333;\n  font-size: 85%;\n  font-weight: initial;\n  padding-top: 3px;\n  padding-bottom: 5px;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-top-color: #FFFFFF;\n  border-top-width: 0;\n}\n\n#daqhfwlbgd .gt_heading {\n  background-color: #FFFFFF;\n  text-align: center;\n  border-bottom-color: #FFFFFF;\n  border-left-style: none;\n  border-left-width: 1px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 1px;\n  border-right-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_bottom_border {\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_col_headings {\n  border-top-style: solid;\n  border-top-width: 2px;\n  border-top-color: #D3D3D3;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  border-left-style: none;\n  border-left-width: 1px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 1px;\n  border-right-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_col_heading {\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: normal;\n  text-transform: inherit;\n  border-left-style: none;\n  border-left-width: 1px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 1px;\n  border-right-color: #D3D3D3;\n  vertical-align: bottom;\n  padding-top: 5px;\n  padding-bottom: 6px;\n  padding-left: 5px;\n  padding-right: 5px;\n  overflow-x: hidden;\n}\n\n#daqhfwlbgd .gt_column_spanner_outer {\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: normal;\n  text-transform: inherit;\n  padding-top: 0;\n  padding-bottom: 0;\n  padding-left: 4px;\n  padding-right: 4px;\n}\n\n#daqhfwlbgd .gt_column_spanner_outer:first-child {\n  padding-left: 0;\n}\n\n#daqhfwlbgd .gt_column_spanner_outer:last-child {\n  padding-right: 0;\n}\n\n#daqhfwlbgd .gt_column_spanner {\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  vertical-align: bottom;\n  padding-top: 5px;\n  padding-bottom: 5px;\n  overflow-x: hidden;\n  display: inline-block;\n  width: 100%;\n}\n\n#daqhfwlbgd .gt_spanner_row {\n  border-bottom-style: hidden;\n}\n\n#daqhfwlbgd .gt_group_heading {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: bold;\n  text-transform: inherit;\n  border-top-style: solid;\n  border-top-width: 2px;\n  border-top-color: #D3D3D3;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  border-left-style: none;\n  border-left-width: 1px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 1px;\n  border-right-color: #D3D3D3;\n  vertical-align: middle;\n  text-align: left;\n}\n\n#daqhfwlbgd .gt_empty_group_heading {\n  padding: 0.5px;\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: bold;\n  border-top-style: solid;\n  border-top-width: 2px;\n  border-top-color: #D3D3D3;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  vertical-align: middle;\n}\n\n#daqhfwlbgd .gt_from_md > :first-child {\n  margin-top: 0;\n}\n\n#daqhfwlbgd .gt_from_md > :last-child {\n  margin-bottom: 0;\n}\n\n#daqhfwlbgd .gt_row {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n  margin: 10px;\n  border-top-style: solid;\n  border-top-width: 1px;\n  border-top-color: #D3D3D3;\n  border-left-style: none;\n  border-left-width: 1px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 1px;\n  border-right-color: #D3D3D3;\n  vertical-align: middle;\n  overflow-x: hidden;\n}\n\n#daqhfwlbgd .gt_stub {\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: initial;\n  text-transform: inherit;\n  border-right-style: solid;\n  border-right-width: 2px;\n  border-right-color: #D3D3D3;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\n#daqhfwlbgd .gt_stub_row_group {\n  color: #333333;\n  background-color: #FFFFFF;\n  font-size: 100%;\n  font-weight: initial;\n  text-transform: inherit;\n  border-right-style: solid;\n  border-right-width: 2px;\n  border-right-color: #D3D3D3;\n  padding-left: 5px;\n  padding-right: 5px;\n  vertical-align: top;\n}\n\n#daqhfwlbgd .gt_row_group_first td {\n  border-top-width: 2px;\n}\n\n#daqhfwlbgd .gt_row_group_first th {\n  border-top-width: 2px;\n}\n\n#daqhfwlbgd .gt_summary_row {\n  color: #333333;\n  background-color: #FFFFFF;\n  text-transform: inherit;\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\n#daqhfwlbgd .gt_first_summary_row {\n  border-top-style: solid;\n  border-top-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_first_summary_row.thick {\n  border-top-width: 2px;\n}\n\n#daqhfwlbgd .gt_last_summary_row {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_grand_summary_row {\n  color: #333333;\n  background-color: #FFFFFF;\n  text-transform: inherit;\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\n#daqhfwlbgd .gt_first_grand_summary_row {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-top-style: double;\n  border-top-width: 6px;\n  border-top-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_last_grand_summary_row_top {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  padding-left: 5px;\n  padding-right: 5px;\n  border-bottom-style: double;\n  border-bottom-width: 6px;\n  border-bottom-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_striped {\n  background-color: rgba(128, 128, 128, 0.05);\n}\n\n#daqhfwlbgd .gt_table_body {\n  border-top-style: solid;\n  border-top-width: 2px;\n  border-top-color: #D3D3D3;\n  border-bottom-style: solid;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_footnotes {\n  color: #333333;\n  background-color: #FFFFFF;\n  border-bottom-style: none;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  border-left-style: none;\n  border-left-width: 2px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 2px;\n  border-right-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_footnote {\n  margin: 0px;\n  font-size: 90%;\n  padding-top: 4px;\n  padding-bottom: 4px;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\n#daqhfwlbgd .gt_sourcenotes {\n  color: #333333;\n  background-color: #FFFFFF;\n  border-bottom-style: none;\n  border-bottom-width: 2px;\n  border-bottom-color: #D3D3D3;\n  border-left-style: none;\n  border-left-width: 2px;\n  border-left-color: #D3D3D3;\n  border-right-style: none;\n  border-right-width: 2px;\n  border-right-color: #D3D3D3;\n}\n\n#daqhfwlbgd .gt_sourcenote {\n  font-size: 90%;\n  padding-top: 4px;\n  padding-bottom: 4px;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n\n#daqhfwlbgd .gt_left {\n  text-align: left;\n}\n\n#daqhfwlbgd .gt_center {\n  text-align: center;\n}\n\n#daqhfwlbgd .gt_right {\n  text-align: right;\n  font-variant-numeric: tabular-nums;\n}\n\n#daqhfwlbgd .gt_font_normal {\n  font-weight: normal;\n}\n\n#daqhfwlbgd .gt_font_bold {\n  font-weight: bold;\n}\n\n#daqhfwlbgd .gt_font_italic {\n  font-style: italic;\n}\n\n#daqhfwlbgd .gt_super {\n  font-size: 65%;\n}\n\n#daqhfwlbgd .gt_footnote_marks {\n  font-size: 75%;\n  vertical-align: 0.4em;\n  position: initial;\n}\n\n#daqhfwlbgd .gt_asterisk {\n  font-size: 100%;\n  vertical-align: 0;\n}\n\n#daqhfwlbgd .gt_indent_1 {\n  text-indent: 5px;\n}\n\n#daqhfwlbgd .gt_indent_2 {\n  text-indent: 10px;\n}\n\n#daqhfwlbgd .gt_indent_3 {\n  text-indent: 15px;\n}\n\n#daqhfwlbgd .gt_indent_4 {\n  text-indent: 20px;\n}\n\n#daqhfwlbgd .gt_indent_5 {\n  text-indent: 25px;\n}\n\n#daqhfwlbgd .katex-display {\n  display: inline-flex !important;\n  margin-bottom: 0.75em !important;\n}\n\n#daqhfwlbgd div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {\n  height: 0px !important;\n}\n</style>\n<table class=\"gt_table\" style=\"table-layout:fixed;\" data-quarto-disable-processing=\"false\" data-quarto-bootstrap=\"false\">\n  <colgroup>\n    <col style=\"width:100px;\"/>\n    <col/>\n    <col/>\n  </colgroup>\n  <thead>\n    <tr class=\"gt_col_headings\">\n      <th class=\"gt_col_heading gt_columns_bottom_border gt_left\" rowspan=\"1\" colspan=\"1\" style=\"text-align: center; font-weight: bold;\" scope=\"col\" id=\"t\"></th>\n      <th class=\"gt_col_heading gt_columns_bottom_border gt_center\" rowspan=\"1\" colspan=\"1\" style=\"text-align: center; font-weight: bold;\" scope=\"col\" id=\"Developer\">Developer</th>\n      <th class=\"gt_col_heading gt_columns_bottom_border gt_center\" rowspan=\"1\" colspan=\"1\" style=\"text-align: center; font-weight: bold;\" scope=\"col\" id=\"User\">User</th>\n    </tr>\n  </thead>\n  <tbody class=\"gt_table_body\">\n    <tr class=\"gt_group_heading_row\">\n      <th colspan=\"3\" class=\"gt_group_heading\" scope=\"colgroup\" id=\"Expression (Quasiquotation)\">Expression (Quasiquotation)</th>\n    </tr>\n    <tr class=\"gt_row_group_first\"><td headers=\"Expression (Quasiquotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"T25l\"><span class='gt_from_md'>One</span></span></td>\n<td headers=\"Expression (Quasiquotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGV4cHIoKWA=\"><span class='gt_from_md'><code>expr()</code></span></span></td>\n<td headers=\"Expression (Quasiquotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGVuZXhwcigpYA==\"><span class='gt_from_md'><code>enexpr()</code></span></span></td></tr>\n    <tr><td headers=\"Expression (Quasiquotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"TWFueQ==\"><span class='gt_from_md'>Many</span></span></td>\n<td headers=\"Expression (Quasiquotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGV4cHJzKClg\"><span class='gt_from_md'><code>exprs()</code></span></span></td>\n<td headers=\"Expression (Quasiquotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGVuZXhwcnMoKWA=\"><span class='gt_from_md'><code>enexprs()</code></span></span></td></tr>\n    <tr class=\"gt_group_heading_row\">\n      <th colspan=\"3\" class=\"gt_group_heading\" scope=\"colgroup\" id=\"Symbol (Quasiquotation)\">Symbol (Quasiquotation)</th>\n    </tr>\n    <tr class=\"gt_row_group_first\"><td headers=\"Symbol (Quasiquotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"T25l\"><span class='gt_from_md'>One</span></span></td>\n<td headers=\"Symbol (Quasiquotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGV4cHIoKWA=\"><span class='gt_from_md'><code>expr()</code></span></span></td>\n<td headers=\"Symbol (Quasiquotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGVuc3ltKClg\"><span class='gt_from_md'><code>ensym()</code></span></span></td></tr>\n    <tr><td headers=\"Symbol (Quasiquotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"TWFueQ==\"><span class='gt_from_md'>Many</span></span></td>\n<td headers=\"Symbol (Quasiquotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGV4cHJzKClg\"><span class='gt_from_md'><code>exprs()</code></span></span></td>\n<td headers=\"Symbol (Quasiquotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGVuc3ltcygpYA==\"><span class='gt_from_md'><code>ensyms()</code></span></span></td></tr>\n    <tr class=\"gt_group_heading_row\">\n      <th colspan=\"3\" class=\"gt_group_heading\" scope=\"colgroup\" id=\"R Base (Quotation)\">R Base (Quotation)</th>\n    </tr>\n    <tr class=\"gt_row_group_first\"><td headers=\"R Base (Quotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"T25l\"><span class='gt_from_md'>One</span></span></td>\n<td headers=\"R Base (Quotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YHF1b3RlKClg\"><span class='gt_from_md'><code>quote()</code></span></span></td>\n<td headers=\"R Base (Quotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: hidden; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGFsaXN0KClg\"><span class='gt_from_md'><code>alist()</code></span></span></td></tr>\n    <tr><td headers=\"R Base (Quotation)  t\" class=\"gt_row gt_left\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"TWFueQ==\"><span class='gt_from_md'>Many</span></span></td>\n<td headers=\"R Base (Quotation)  Developer\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"YHN1YnN0aXR1dGUoKWA=\"><span class='gt_from_md'><code>substitute()</code></span></span></td>\n<td headers=\"R Base (Quotation)  User\" class=\"gt_row gt_center\" style=\"border-left-width: 1px; border-left-style: hidden; border-left-color: #000000; border-right-width: 1px; border-right-style: hidden; border-right-color: #000000; border-top-width: 1px; border-top-style: hidden; border-top-color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #000000;\"><span data-qmd-base64=\"YGFzLmxpc3Qoc3Vic3RpdHV0ZSguLi4oKSkpYA==\"><span class='gt_from_md'><code>as.list(substitute(...()))</code></span></span></td></tr>\n  </tbody>\n  \n  \n</table>\n</div>\n```\n\n:::\n:::\n\n\n- Non-base functions are from **rlang**\n- **Developer** - From you, direct, fixed, interactive\n- **User** - From the user, indirect, varying, programmatic\n\nAlso: \n\n- `bquote()` provides a limited form of quasiquotation\n- `~`, the formula, is a quoting function (see [Section 20.3.4](https://adv-r.hadley.nz/evaluation.html#quosure-impl))\n\n### `expr()` and `exprs()` {-}\n\n::: {.cell}\n\n```{.r .cell-code}\nexpr(x + y)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> x + y\n```\n\n\n:::\n\n```{.r .cell-code}\nexprs(exp1 = x + y, exp2 = x * y)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> $exp1\n#> x + y\n#> \n#> $exp2\n#> x * y\n```\n\n\n:::\n:::\n\n\n### `enexpr()`^[`enexpr()` = **en**rich `expr()`] and `enexprs()` {-}\n\n::: {.cell}\n\n```{.r .cell-code}\nf <- function(x) enexpr(x)\nf(a + b + c)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> a + b + c\n```\n\n\n:::\n\n```{.r .cell-code}\nf2 <- function(x, y) enexprs(exp1 = x, exp2 = y)\nf2(x = a + b, y = c + d)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> $exp1\n#> a + b\n#> \n#> $exp2\n#> c + d\n```\n\n\n:::\n:::\n\n\n### `ensym()` and `ensyms()` {-}\n\n- **[Remember](https://adv-r.hadley.nz/expressions.html#symbols):** Symbol represents the name of an object. Can only be length 1.\n- These are stricter than `enexpr/s()`\n\n\n::: {.cell}\n\n```{.r .cell-code}\nf <- function(x) ensym(x)\nf(a)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> a\n```\n\n\n:::\n\n```{.r .cell-code}\nf2 <- function(x, y) ensyms(sym1 = x, sym2 = y)\nf2(x = a, y = \"b\")\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> $sym1\n#> a\n#> \n#> $sym2\n#> b\n```\n\n\n:::\n:::\n\n\n\n## Unquoting\n\n**Selectively evaluate parts of an expression**\n\n- Merges ASTs with template\n- 1 argument `!!` (**unquote**, **bang-bang**)\n  - Unquoting a *function call* evaluates and returns results\n  - Unquoting a *function (name)* replaces the function (alternatively use `call2()`)\n- \\>1 arguments `!!!` (**unquote-splice**, **bang-bang-bang**, **triple bang**)\n- `!!` and `!!!` only work like this inside quoting function using rlang\n\n### Basic unquoting {-}\n\n**One argument**\n\n::: {.cell}\n\n```{.r .cell-code}\nx <- expr(a + b)\ny <- expr(c / d)\n```\n:::\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nexpr(f(x, y))      # No unquoting\n#> f(x, y)\nexpr(f(!!x, !!y))  # Unquoting\n#> f(a + b, c/d)\n```\n:::\n\n\n**Multiple arguments**\n\n::: {.cell}\n\n```{.r .cell-code}\nz <- exprs(a + b, c + d)\nw <- exprs(exp1 = a + b, exp2 = c + d)\n```\n:::\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nexpr(f(z))      # No unquoting\n#> f(z)\nexpr(f(!!!z))   # Unquoting\n#> f(a + b, c + d)\nexpr(f(!!!w))   # Unquoting when named\n#> f(exp1 = a + b, exp2 = c + d)\n```\n:::\n\n\n\n### Special usages or cases {-}\n\nFor example, get the AST of an expression\n\n::: {.cell}\n\n```{.r .cell-code}\nlobstr::ast(x)\n#> x\nlobstr::ast(!!x)\n#> █─`+` \n#> ├─a \n#> └─b\n```\n:::\n\n\n\nUnquote *function call*\n\n::: {.cell}\n\n```{.r .cell-code}\nexpr(f(!!mean(c(100, 200, 300)), y))\n#> f(200, y)\n```\n:::\n\n\nUnquote *function*\n\n::: {.cell}\n\n```{.r .cell-code}\nf <- expr(sd)\nexpr((!!f)(x))\n#> sd(x)\nexpr((!!f)(!!x + !!y))\n#> sd(a + b + c/d)\n```\n:::\n\n\n## Non-quoting\n\nOnly `bquote()` provides a limited form of quasiquotation.\n\nThe rest of base selectively uses or does not use quoting (rather than unquoting). \n\nFour basic forms of quoting/non-quoting:\n\n1. **Pair of functions** - Quoting and non-quoting\n    - e.g., `$` (quoting) and `[[` (non-quoting)\n2. **Pair of Arguments** - Quoting and non-quoting\n    - e.g., `rm(...)` (quoting) and `rm(list = c(...))` (non-quoting)\n3. **Arg to control quoting**\n    - e.g., `library(rlang)` (quoting) and `library(pkg, character.only = TRUE)` (where `pkg <- \"rlang\"`)\n4. **Quote if evaluation fails**\n    - `help(var)` - Quote, show help for var\n    - `help(var)` (where `var <- \"mean\"`) - No quote, show help for mean\n    - `help(var)` (where `var <- 10`) - Quote fails, show help for var\n\n\n## ... (dot-dot-dot) [When using ... with quoting]\n\n- Sometimes need to supply an *arbitrary* list of expressions or arguments in a function (`...`)\n- But need a way to use these when we don't necessarily have the names\n- Remember `!!` and `!!!` only work with functions that use rlang\n- Can use `list2(...)` to turn `...` into \"tidy dots\" which *can* be unquoted and spliced\n- Require `list2()` if going to be passing or using `!!` or `!!!` in `...`\n- `list2()` is a wrapper around `dots_list()` with the most common defaults\n\n**No need for `list2()`**\n\n::: {.cell}\n\n```{.r .cell-code}\nd <- function(...) data.frame(list(...))\nd(x = c(1:3), y = c(2, 4, 6))\n#>   x y\n#> 1 1 2\n#> 2 2 4\n#> 3 3 6\n```\n:::\n\n\n**Require `list2()`**\n\n::: {.cell}\n\n```{.r .cell-code}\nvars <- list(x = c(1:3), y = c(2, 4, 6))\nd(!!!vars)\n#> Error in !vars: invalid argument type\nd2 <- function(...) data.frame(list2(...))\nd2(!!!vars)\n#>   x y\n#> 1 1 2\n#> 2 2 4\n#> 3 3 6\n# Same result but x and y evaluated later\nvars_expr <- exprs(x = c(1:3), y = c(2, 4, 6))\nd2(!!!vars_expr)  \n#>   x y\n#> 1 1 2\n#> 2 2 4\n#> 3 3 6\n```\n:::\n\n\nGetting argument names (symbols) from variables\n\n::: {.cell}\n\n```{.r .cell-code}\nnm <- \"z\"\nval <- letters[1:4]\nd2(x = 1:4, !!nm := val)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#>   x z\n#> 1 1 a\n#> 2 2 b\n#> 3 3 c\n#> 4 4 d\n```\n\n\n:::\n:::\n\n\n## `exec()` [Making your own ...] {-}\n\nWhat if your function doesn't have tidy dots?\n\n\nCan't use `!!` or `:=` if doesn't support rlang or dynamic dots\n\n::: {.cell}\n\n```{.r .cell-code}\nmy_mean <- function(x, arg_name, arg_val) {\n  mean(x, !!arg_name := arg_val)\n}\n\nmy_mean(c(NA, 1:10), arg_name = \"na.rm\", arg_val = TRUE)     \n#> Error in `my_mean()`:\n#> ! `:=` can only be used within dynamic dots.\n```\n:::\n\n\nLet's use the ... from `exec()`\n\n::: {.cell}\n\n```{.r .cell-code}\nexec(.fn, ..., .env = caller_env())\n```\n:::\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmy_mean <- function(x, arg_name, arg_val) {\n  exec(\"mean\", x, !!arg_name := arg_val)\n}\n\nmy_mean(c(NA, 1:10), arg_name = \"na.rm\", arg_val = TRUE)     \n#> [1] 5.5\n```\n:::\n\n\nNote that you do not unquote `arg_val`.\n \nAlso `exec` is useful for mapping over a list of functions:\n\n\n::: {.cell}\n\n```{.r .cell-code}\nx <- c(runif(10), NA)\nfuns <- c(\"mean\", \"median\", \"sd\")\npurrr::map_dbl(funs, exec, x, na.rm = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n#> [1] 0.4445205 0.4886247 0.3166360\n```\n\n\n:::\n:::\n\n\n   \n##  Base R `do.call` {-}\n\n`do.call(what, args)`\n\n- `what` is a function to call\n- `args` is a list of arguments to pass to the function.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nnrow(mtcars)\n#> [1] 32\nmtcars3 <- do.call(\"rbind\", list(mtcars, mtcars, mtcars))\nnrow(mtcars3)\n#> [1] 96\n```\n:::\n\n \n\n### Exercise 19.5.5 #1 {-}\n\nOne way to implement `exec` is shown here: Describe how it works. What are the key ideas?\n\n\n::: {.cell}\n\n```{.r .cell-code}\nexec_ <- function(f, ..., .env = caller_env()){\n  args <- list2(...)\n  do.call(f, args, envir  = .env)\n}\n```\n:::\n\n\n## Case Studies (side note)\n\nSometimes you want to run a bunch of models, without having to copy/paste each one.\n\nBUT, you also want the summary function to show the appropriate model call, \nnot one with hidden variables (e.g., `lm(y ~ x, data = data)`). \n\nWe can achieve this by building expressions and unquoting as needed:\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(purrr)\n\nvars <- data.frame(x = c(\"hp\", \"hp\"),\n                   y = c(\"mpg\", \"cyl\"))\n\nx_sym <- syms(vars$x)\ny_sym <- syms(vars$y)\n\nformulae <- map2(x_sym, y_sym, \\(x, y) expr(!!y ~ !!x))\nformulae\n#> [[1]]\n#> mpg ~ hp\n#> \n#> [[2]]\n#> cyl ~ hp\nmodels <- map(formulae, \\(f) expr(lm(!!f, data = mtcars)))\nsummary(eval(models[[1]]))\n#> \n#> Call:\n#> lm(formula = mpg ~ hp, data = mtcars)\n#> \n#> Residuals:\n#>     Min      1Q  Median      3Q     Max \n#> -5.7121 -2.1122 -0.8854  1.5819  8.2360 \n#> \n#> Coefficients:\n#>             Estimate Std. Error t value Pr(>|t|)    \n#> (Intercept) 30.09886    1.63392  18.421  < 2e-16 ***\n#> hp          -0.06823    0.01012  -6.742 1.79e-07 ***\n#> ---\n#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n#> \n#> Residual standard error: 3.863 on 30 degrees of freedom\n#> Multiple R-squared:  0.6024,\tAdjusted R-squared:  0.5892 \n#> F-statistic: 45.46 on 1 and 30 DF,  p-value: 1.788e-07\n```\n:::\n\n\nAs a function:\n\n::: {.cell}\n\n```{.r .cell-code}\nlm_df <- function(df, data) {\n  x_sym <- map(df$x, as.symbol)\n  y_sym <- map(df$y, as.symbol)\n  data <- enexpr(data)\n  \n  formulae <- map2(x_sym, y_sym, \\(x, y) expr(!!y ~ !!x))\n  models <- map(formulae, \\(f) expr(lm(!!f, !!data)))\n  \n  map(models, \\(m) summary(eval(m)))\n}\n\nvars <- data.frame(x = c(\"hp\", \"hp\"),\n                   y = c(\"mpg\", \"cyl\"))\nlm_df(vars, data = mtcars)\n#> [[1]]\n#> \n#> Call:\n#> lm(formula = mpg ~ hp, data = mtcars)\n#> \n#> Residuals:\n#>     Min      1Q  Median      3Q     Max \n#> -5.7121 -2.1122 -0.8854  1.5819  8.2360 \n#> \n#> Coefficients:\n#>             Estimate Std. Error t value Pr(>|t|)    \n#> (Intercept) 30.09886    1.63392  18.421  < 2e-16 ***\n#> hp          -0.06823    0.01012  -6.742 1.79e-07 ***\n#> ---\n#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n#> \n#> Residual standard error: 3.863 on 30 degrees of freedom\n#> Multiple R-squared:  0.6024,\tAdjusted R-squared:  0.5892 \n#> F-statistic: 45.46 on 1 and 30 DF,  p-value: 1.788e-07\n#> \n#> \n#> [[2]]\n#> \n#> Call:\n#> lm(formula = cyl ~ hp, data = mtcars)\n#> \n#> Residuals:\n#>      Min       1Q   Median       3Q      Max \n#> -2.27078 -0.74879 -0.06417  0.63512  1.74067 \n#> \n#> Coefficients:\n#>             Estimate Std. Error t value Pr(>|t|)    \n#> (Intercept) 3.006795   0.425485   7.067 7.41e-08 ***\n#> hp          0.021684   0.002635   8.229 3.48e-09 ***\n#> ---\n#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n#> \n#> Residual standard error: 1.006 on 30 degrees of freedom\n#> Multiple R-squared:  0.693,\tAdjusted R-squared:  0.6827 \n#> F-statistic: 67.71 on 1 and 30 DF,  p-value: 3.478e-09\n```\n:::\n\n",
      6     "supporting": [
      7       "19_files"
      8     ],
      9     "filters": [
     10       "rmarkdown/pagebreak.lua"
     11     ],
     12     "includes": {},
     13     "engineDependencies": {},
     14     "preserve": {},
     15     "postProcess": true
     16   }
     17 }