1#' Create a symbol or list of symbols 2#' 3#' These functions take strings as input and turn them into symbols. 4#' 5#' @param x A string or list of strings. 6#' @return A symbol for `sym()` and a list of symbols for `syms()`. 7#' @export 8#' @examples 9#' # The empty string returns the missing argument: 10#' sym("") 11#' 12#' # This way sym() and as_string() are inverse of each other: 13#' as_string(missing_arg()) 14#' sym(as_string(missing_arg())) 15sym <- function(x) { 16 if (is_symbol(x)) { 17 return(x) 18 } 19 if (identical(x, "")) { 20 return(missing_arg()) 21 } 22 if (!is_string(x)) { 23 abort("Only strings can be converted to symbols") 24 } 25 .Call(rlang_symbol, x) 26} 27#' @rdname sym 28#' @export 29syms <- function(x) { 30 map(x, sym) 31} 32 33#' Is object a symbol? 34#' @param x An object to test. 35#' @param name An optional name or vector of names that the symbol 36#' should match. 37#' @export 38is_symbol <- function(x, name = NULL) { 39 if (typeof(x) != "symbol") { 40 return(FALSE) 41 } 42 if (is_null(name)) { 43 return(TRUE) 44 } 45 as_string(x) %in% name 46} 47 48#' Cast symbol to string 49#' 50#' `as_string()` converts [symbols][sym] to character strings. 51#' 52#' @param x A string or symbol. If a string, the attributes are 53#' removed, if any. 54#' @return A character vector of length 1. 55#' 56#' @section Unicode tags: 57#' 58#' Unlike [base::as.symbol()] and [base::as.name()], `as_string()` 59#' automatically transforms unicode tags such as `"<U+5E78>"` to the 60#' proper UTF-8 character. This is important on Windows because: 61#' 62#' * R on Windows has no UTF-8 support, and uses native encoding instead. 63#' 64#' * The native encodings do not cover all Unicode characters. For 65#' example, Western encodings do not support CKJ characters. 66#' 67#' * When a lossy UTF-8 -> native transformation occurs, uncovered 68#' characters are transformed to an ASCII unicode tag like `"<U+5E78>"`. 69#' 70#' * Symbols are always encoded in native. This means that 71#' transforming the column names of a data frame to symbols might be 72#' a lossy operation. 73#' 74#' * This operation is very common in the tidyverse because of data 75#' masking APIs like dplyr where data frames are transformed to 76#' environments. While the names of a data frame are stored as a 77#' character vector, the bindings of environments are stored as 78#' symbols. 79#' 80#' Because it reencodes the ASCII unicode tags to their UTF-8 81#' representation, the string -> symbol -> string roundtrip is 82#' more stable with `as_string()`. 83#' 84#' @seealso [as_name()] for a higher-level variant of `as_string()` 85#' that automatically unwraps quosures. 86#' @examples 87#' # Let's create some symbols: 88#' foo <- quote(foo) 89#' bar <- sym("bar") 90#' 91#' # as_string() converts symbols to strings: 92#' foo 93#' as_string(foo) 94#' 95#' typeof(bar) 96#' typeof(as_string(bar)) 97#' @export 98as_string <- function(x) { 99 if (is_string(x)) { 100 attributes(x) <- NULL 101 return(x) 102 } 103 104 if (is_symbol(x)) { 105 return(.Call(rlang_sym_as_character, x)) 106 } 107 108 abort_coercion(x, "a string") 109} 110 111namespace_sym <- quote(`::`) 112namespace2_sym <- quote(`:::`) 113dollar_sym <- quote(`$`) 114dot_data_sym <- quote(.data) 115dots_sym <- quote(...) 116at_sym <- quote(`@`) 117tilde_sym <- quote(`~`) 118colon_equals_sym <- quote(`:=`) 119brace_sym <- quote(`{`) 120dots_sym <- quote(...) 121function_sym <- quote(`function`) 122dot_sym <- quote(.) 123pipe_sym <- quote(`%>%`) 124