It is obvious that after writing almost 20 R packages, Xie(2020) would find that she has accumulated several utility functions that she must have definitely used across different packages, so let’s understand how they were extracted into a separate package. Initially, ‘:::’ was used to access these internal utility functions. But now with xfun, we can easily export these functions and most important thing to keep in mind is that these functions are documented as well. It will be easy and better to use them. This page shows examples of a subset of functions in this package. To get the list of the functions, see the help page help(package = =’xfun’). The source package is available on Github: https://github.com/yihui/xfun.(Xie, 2020)

No More Partial Matching For Lists!

Xie(20202) had always encountered a problem with the partial matching in the lists. e.g., when we want x$p but the element p does not exist in the list x , it returns the value x$pqr if pqr exists in x . To avoid such conditions, the strict lists are created. A strict list is a list for which the partial matching of the $ operator is disabled. The functions xfun::strict_list() and xfun::as_strict_list() are equivalents to base::list() and base::as.list() respectively which always return as strict list e.g.,

library(xfun)
## 
## Attaching package: 'xfun'
## The following objects are masked from 'package:base':
## 
##     attr, isFALSE
(z = strict_list(aaa = "I am aaa", b = 1:5))
## $aaa
## [1] "I am aaa"
## 
## $b
## [1] 1 2 3 4 5
z$a # NULL (strict matching)
## NULL
z$aaa # I am aaa 
## [1] "I am aaa"
z$b
## [1] 1 2 3 4 5
z$c = "you can create a new element"
z2 = unclass(z)  # a normal list
z2$a  # partial matching
## [1] "I am aaa"
z3 = as_strict_list(z2)  # a strict list again
z3$a  # NULL (strict matching) again!
## NULL

Now looking at the similar case, the default partial matching in attr() can be annoying too. Thus, the function xfun::attr() is simply a shorthand of attr(…, exact = TRUE). So, it is I either want it or I don’t want it, there is nothing like “I probably want it”.(Xie, 2020)

Output Character Vectors For Human Eye

Your eyes might get distracted when R prints a character vector by the indices like 1, escape sequence and double quotes too. To see a character vector in its “raw” form, you can use cat(…, sep = ‘\n’). The function raw_string() marks a character vector as “raw”, and the corresponding printing function will call cat(sep = ‘\n’) to print the character vector to the console.(Xie, 2020)

library(xfun)
raw_string(head(LETTERS))
## A
## B
## C
## D
## E
## F
(x = c("a \"b\"", "hello\tworld!"))
## [1] "a \"b\""      "hello\tworld!"
raw_string(x)  # this is more likely to be what you want to see
## a "b"
## hello    world!

Search and replace string files

Initially, according to Xie(2020) we had only choices inclusive of grep and sed to search and replace string in multiple files. RStudio did not provide the feature any soon(you could only search in the currently opened file). But now, functions such as gsub_files(),gsub_dir() and gsub_ext() can be usedto search and replace multiple files, under one directory. Also, you should note that the files are assumed to be encoded in UTF-8. All functions are based on gsub_file(), which perform searching and replacing in a single file.(Xie, 2020) e.g.,

library(xfun)
f = tempfile()
writeLines(c("hello", "world"), f)
gsub_file(f, "world", "woRld", fixed = TRUE)
file_string(f)
## hello
## woRld

Manipulate filename extension

Functions file_ext() and sans_ext() are based on functions in tools. The function with_ext() is used to add or replace extensions of the filenames, and also it is vectorised.(Xie, 2020).

library(xfun)
p = c("abc.doc", "def123.tex", "path/to/foo.Rmd")
file_ext(p)
## [1] "doc" "tex" "Rmd"
sans_ext(p)
## [1] "abc"         "def123"      "path/to/foo"
with_ext(p, ".txt")
## [1] "abc.txt"         "def123.txt"      "path/to/foo.txt"
with_ext(p, c(".ppt", ".sty", ".Rnw"))
## [1] "abc.ppt"         "def123.sty"      "path/to/foo.Rnw"
with_ext(p, "html")
## [1] "abc.html"         "def123.html"      "path/to/foo.html"

Types of Operating Systems

The series of functions is_linux(), is_macos(),is_unix() and is_windows. According to Xie(2020), we can test the types of OS, by using the information that we get from .Platform and Sys.info().(Xie, 2020), e.g.,

xfun::is_macos()
## [1] FALSE
xfun::is_unix()
## [1] FALSE
xfun::is_linux()
## [1] FALSE
xfun::is_windows()
## [1] TRUE

Loading and attaching packages

It is commonly observed or we often use library() multiple times to attach a series of packages in the beginning of their scripts. Now according to Xie(2020), this can be vectorised easily by using the function xfun::pkg_attach(), e.g.,

library(testit)
library(parallel)
library(tinytex)
library(mime)

This is equilavent to

xfun::pkg_attach(c("testit", "parallel", "tinytex", "mime"))

There are also scripts, if the packages are not available, they contain the code to install them, e.g.,

if (!requireNamespace("tinytex")) install.packages("tinytex")
library(tinytex)

This I also equivalent to,

xfun::pkg_attach2("tinytex")

This function here, is a shorthand of pkg_attach(., install = TRUE). This installs the package if it is not available already. Advantage of this is that, it can handle multiple packages too. If you have to check that a package is loadable or not, you can simply us loadable(). Xie(2020).

Read/Write files in UTF-8

To read and write files in UTF-8 we can use functions such as read_utf8() and write_utf8(). These are simple alternatives of the functions readLines() and writeLines().Xie(2020).

Convert numbers to English words

Numbers can be converted to English words by using the function numbers_to_words(). Short format for this function is n2w().Xie(2020).

n2w(0, cap = TRUE)
## [1] "Zero"
n2w(seq(0, 122, 12), and = TRUE)
##  [1] "zero"                   "twelve"                 "twenty-four"           
##  [4] "thirty-six"             "forty-eight"            "sixty"                 
##  [7] "seventy-two"            "eighty-four"            "ninety-six"            
## [10] "one hundred and eight"  "one hundred and twenty"
n2w(1e+06)
## [1] "one million"
n2w(1e+11 + 416546846)
## [1] "one hundred billion, four hundred sixteen million, five hundred forty-six thousand, eight hundred forty-six"
n2w(-6544684684)
## [1] "minus six billion, five hundred forty-four million, six hundred eighty-four thousand, six hundred eighty-four"
n2w(1e+5 - 2)
## [1] "ninety-nine thousand, nine hundred ninety-eight"

Check reverse dependencies of a package

It is a complete NO to run R CMD check on the reverse dependencies of knitr and rmarkdown because there is a huge number of reverse dependencies attached to them. We can rather use rev_check() which was developed by Xie(2020), to check the reverse dependencies of the packages.

References

Xie, Y., 2020. An Introduction To Xfun. [online] Cran.r-project.org. Available at: https://cran.r-project.org/web/packages/xfun/vignettes/xfun.html [Accessed 1 April 2020].