在R中将表达式捕获为函数体 [英] capturing an expression as a function body in R

查看:55
本文介绍了在R中将表达式捕获为函数体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个将表达式作为输入并返回以该表达式为主体的函数的程序.

I'm trying to write a program that takes an expression as an input and returns a function with that expression bound as its body.

caller <- function (expr, params) {

    Function <- function (params, body, env = parent.frame()) {
        # returns a function

    }

    Function(params, body = expr)
}

func <- caller (a + b, c('a', 'b'))

func(1, 2)
[1] 3

我可以很容易地通过使用类似的方法来绑定参数

I can bind the parameters quite easily, by using something like

params <- c('a', 'b')
f <- function() {} 
formals(f) <- structure(
    replicate(length(params), NULL),
    names = params
)

我想不出一种将表达式动态添加为正文的方法.我试过使用proxy()和从pryr库改编make_function,但是我不能完全正常工作.我最好的尝试是

I'm having trouble coming up with a way of dynamically adding the expression as the body. I've tried use substitute(), and adapting make_function from the pryr library, but I can't quite get things to work. My best attempt is

    body(f, parent.frame()) <- as.list( match.call() )[-1]$body

我也无法使它与替代品一起使用.关于如何绑定身体以使最顶层的程序按预期工作的任何想法?

I couldn't get this to work with substitute either. Any thoughts on how to bind the body in so that the topmost program works as expected?

我在SO上看到了类似的问题,但是解决方案似乎不能满足这个问题.

I've seen similar questions on SO, but the solutions don't seem to satistfy this problem.

推荐答案

这里是一种允许没有默认值的参数的解决方案.传递参数名称也更容易,因为它们不必用引号引起来.

Here is a solution to allow parameters with no default value. It's also easier to pass parameters names, as they don't have to be enclosed with quotes.

请检查以下代码中的注释:

Please check the comments in the code below:

g <- function(...)
{
    # Get the arguments as unevaluated expressions:

    L <- as.list(substitute(list(...)))[-1]

    # The first argument is the body expression (technically a call object):

    expr <- L[[1]]

    # If the expression is not enclosed in curly braces, let's force it:

    if( as.character(expr[[1]]) != "{" ) expr <- call("{", expr)

    # Drop the first argument:

    L <- L[-1]

    # Mark symbols to be used as names for missing parameters:

    filter <- vapply(L, is.symbol, logical(1))

    params <- L

    # The obscure expression "formals(function(x){})$x" returns a missing value, something really arcane ;-) :

    params[filter] <- list(formals(function(x){})$x)

    # Here the symbols are used as names:

    names(params)[filter] <- vapply(L[filter], as.character, character(1))

    # Now the result:

    f <- function(){}

    formals(f) <- params

    body(f) <- expr

    # Just to make it nicier, let's define the enclosing environment as if the function were created outside g:

    environment(f) <- parent.frame()

    f
}

一些测试:

> g(a+b, a, b=1)
function (a, b = 1) 
{
    a + b
}


> f <- g({x <- a+b; x^2}, a, b)
> f
function (a, b) 
{
    x <- a + b
    x^2
}
> f(2,3)
[1] 25
> f(1)
Error in a + b : 'b' is missing

> g(a+b, a=2, b=2)()
[1] 4

这篇关于在R中将表达式捕获为函数体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆