Chapter 21 Translating R Code

21.2.3 Basic tag functions

Why do we use list2 here and not just list when they have the same output?

## $a
## [1] 1
## 
## [[2]]
## [1] 2
## 
## $b
## [1] 3
## 
## [[4]]
## [1] 4
## $a
## [1] 1
## 
## [[2]]
## [1] 2
## 
## $b
## [1] 3
## 
## [[4]]
## [1] 4

list2 supports “tidy dots” and unquote splicing. Most of the time it won’t make a difference, but there are instances where using list2 does matter:

## $named
## list()
## 
## $unnamed
## $unnamed[[1]]
## $unnamed[[1]]$letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"

When we use list here the letters come back as unnamed elements, but if we use !!! with list2 we return the letters as named arguments

## $named
## $named$letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## 
## 
## $unnamed
## named list()

21.2.4 Tag functions

Can we explain this function?

## function (...) 
## {
##     dots <- dots_partition(...)
##     attribs <- html_attributes(dots$named)
##     children <- map_chr(dots$unnamed, escape)
##     html(paste0("<b", attribs, ">", paste(children, collapse = ""), 
##         "</b>"))
## }

expr(... = ) creates an expression with the argument name ... with an empty values.

21.1 21.3.3 to_math()

Hadley uses eval_bare which is described as:

eval_bare() is a lower-level version of function base::eval(). Technically, it is a simple wrapper around the C function Rf_eval(). You generally don’t need to use eval_bare() instead of eval(). Its main advantage is that it handles stack-sensitive (calls such as return(), on.exit() or parent.frame()) more consistently when you pass an enviroment of a frame on the call stack.

Why use this instead of tidy_eval?

21.2 21.3.5

switch_expr is an rlang internal, rlang:::switch_expr that ….

function (.x, ...) 
{
    switch(expr_type_of(.x), ...)
}
<bytecode: 0x7fdba4adc070>
<environment: namespace:rlang>

In Chapter 18 Hadley defines the flat_map_chr function that….

## [1] "a" "a" "a" "b" "b" "b" "c"

21.3 21.3.6 Unknown functions

My understanding of the LaTeX example starts to break down here. Can we go over the code chunks and comment them below?

all_calls_rec <- function(x) {
  switch_expr(x,
    constant = ,
    symbol =   character(),
    call = {
      fname <- as.character(x[[1]])
      children <- flat_map_chr(as.list(x[-1]), all_calls)
      c(fname, children)
    }
  )
}
all_calls <- function(x) {
  unique(all_calls_rec(x))
}

all_calls(expr(f(g + b, c, d(a))))
#> [1] "f" "+" "d"

unknown_op <- function(op) {
  new_function(
    exprs(... = ),
    expr({
      contents <- paste(..., collapse = ", ")
      paste0(!!paste0("\\mathrm{", op, "}("), contents, ")")
    })
  )
}
unknown_op("foo")
#> function (...) 
#> {
#>     contents <- paste(..., collapse = ", ")
#>     paste0("\\mathrm{foo}(", contents, ")")
#> }
#> <environment: 0x4d608b8>