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)
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)
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!
We surely have used paste(readLines(‘foo’), collapse = ‘\n’) many times. There is a simple wrapper function which can be used instead of this which is, xfun::file_string(). Well now this function also makes use of raw_string, due to this you can see the content of the file in the console.(Xie, 2020) e.g.,
f = system.file("LICENSE", package = "xfun")
xfun::file_string(f)
## YEAR: 2018
## COPYRIGHT HOLDER: Yihui Xie
as.character(xfun::file_string(f)) # essentially a character string
## [1] "YEAR: 2018\nCOPYRIGHT HOLDER: Yihui Xie"
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
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"
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
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).
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).
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"
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.
We all have been using sessionInfo() to get the information of the R version, Platform, System it is running under, Matrix products, Random number generation, Locale, Attached base packages.etc. The function session_info() gives us additional information in the session information, such as the Pandoc version when rmarkdown is used. It tweaks the output of sessionInfo(), and makes it possible for the other packages to append information in the output of session_info(). Xie(2020).
Here, you can also choose to print the version of the packages that you specify, e.g.,
xfun::session_info(c("xfun", "rmarkdown", "knitr", "tinytex"), dependencies = FALSE)
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 18363)
##
## Locale:
## LC_COLLATE=English_India.1252 LC_CTYPE=English_India.1252
## LC_MONETARY=English_India.1252 LC_NUMERIC=C
## LC_TIME=English_India.1252
##
## Package version:
## knitr_1.28 rmarkdown_2.1 tinytex_0.21 xfun_0.12
##
## Pandoc version: 1.19.2.1
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].