Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I turn a vector of character strings (each giving commands) into a function in R?

Tags:

function

r

I am trying to build a function that creates and outputs a new function (which I will call the output-function for convenience) from its inputs. I am able to generate the lines of code I want for the output-function as character strings and I have put this into a character vector that goes through the commands I want in the body of the function. However, I'm having trouble turning this into a function to give as the output.

I have observed that I can extract the body of a function using the body command and I can turn this into a character vector. For example, here is what you get when you apply this to the matrix function:

body(matrix)

{
    if (is.object(data) || !is.atomic(data)) 
        data <- as.vector(data)
    .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), 
        missing(ncol)))
}

COMMANDS <- as.character(body(matrix))
COMMANDS

[1] "{"                                                                                 
[2] "if (is.object(data) || !is.atomic(data)) data <- as.vector(data)"                  
[3] ".Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), missing(ncol)))"

However, I don't know how to reverse this process --- i.e., if I have constructed a character vector containing my commands, how do I create a function with this set of commands as the body?

like image 991
Ben Avatar asked Dec 29 '25 06:12

Ben


1 Answers

A function can be created from a list using as.function. The list has to include a single unnamed element of type "language" that acts as the function's body, with any named items in the list being interpreted as the function's arguments.

To create the function body from a string, we can convert the string to a language object using str2lang.

This means that we can easily write a function that creates functions from strings like this:

make_func <- function(..., body) {
  as.function(c(..., str2lang(body)))
}

so, for example:

hello <- make_func(body = "print('hello world')")

hello()
#> [1] "hello world"

Or, if our function needs arguments:

add_one <- make_func(x = 1, body = "{ x <- x + 1; return(x) }")

add_one(22)
#> [1] 23

As others have pointed out in the comments though, it's rarely necessary to go through the steps of converting to character, since we can use language objects directly.

For example, to recreate matrix, we could do:

my_matrix <- as.function(c(formals(matrix), body(matrix)))
my_matrix(1:9, ncol = 3)
#>      [,1] [,2] [,3]
#> [1,]    1    4    7
#> [2,]    2    5    8
#> [3,]    3    6    9

If, for some reason, you have a character vector representing several lines of code, you can simply paste them together with a newline character. Note that you will need to ensure that the result is wrapped in curly braces for it to be parsed by str2lang. So in your example, we can do:

my_mat <- make_func(data = NA, ncol = 1, nrow = 1, byrow = FALSE, 
                    dimnames = list(NULL),
                    body = paste0(paste(code_lines, collapse = '\n'), '}'))

my_mat(1:9, ncol = 3)
#>      [,1] [,2] [,3]
#> [1,]    1    4    7
#> [2,]    2    5    8
#> [3,]    3    6    9
like image 148
Allan Cameron Avatar answered Jan 01 '26 19:01

Allan Cameron