目前,至少,这是一个为我学习的练习,所以实际功能或其复杂性不是问题。假设我编写了一个函数,其参数列表包含一些输入变量和一个函数名,作为字符串传递。然后,此函数在内部计算一些变量,并决定"如何将它们提供给我传入的功能名称。
对于非原始函数,我可以这样做(对于这个例子,假设我的funcname
函数不具有除最多(x,y,z)
以外的任何参数。如果他们这样做,我必须写一些代码用于搜索匹配的names(formals(get(funcname)))
,以便不删除其他参数):
foo <- function (a,b,funcname) {
x <- 2*a
y <- a+3*b
z <- -b
formals(get(funcname)) <- list(x=x, y=y, z=z)
bar <- get(funcname)()
return(bar)
}
好的是,即使函数funcname
没有错误也会执行,即使它没有使用x
,y
或z
(所以只要没有其他没有违约的参数。)
&#34;原语&#34;的问题功能是我不知道如何找到或修改他们的形式。除了写一个包装器,例如foosin <-function(x) sin(x)
,有没有办法设置我的foo
函数来处理原始和非原始函数名作为输入参数?
答案 0 :(得分:4)
formals(args(FUN))
可用于获取原始函数的形式。
您可以在现有功能中添加if
语句。
> formals(sum)
# NULL
> foo2 <- function(x) {
if(is.primitive(x)) formals(args(x)) else formals(x)
## formals(if(is.primitive(x)) args(x) else x) is another option
}
> foo2(sum)
# $...
#
#
# $na.rm
# [1] FALSE
#
> foo2(with)
# $data
#
#
# $expr
#
#
# $...
答案 1 :(得分:1)
在理查德S的回应基础上,我最终做了以下事情。发布以防万一其他人尝试过像我一样奇怪的事情。
编辑:我认为需要进行更多的类型检查。 coleqn
可能是。{1}}
对象的名称,在这种情况下get(coleqn)
将返回一些数据。可能我需要
在if(is.function(rab))
之后添加if(!is.null(rab))
。 (当然,鉴于我根据自己的需要编写了函数,如果我愚蠢到传递一个对象,我应该得到的东西:-))。
# "coleqn" is the input argument, which is a string that could be either a function
# name or an expression.
rab<-tryCatch(get(coleqn),error=function(x) {} )
#oops, rab can easily be neither NULL nor a closure. Damn.
if(!is.null(rab)) {
# I believe this means it must be a function
# thanks to Richard Scriven of SO for this fix to handle primitives
# we are not allowed to redefine primitive's formals.
qq <- list(x=x,y=y,z=z)
# matchup the actual formals names
# by building a list of valid arguments to pass to do.call
argk<-NULL
argnames<-names(formals(args(coleqn)))
for(j in 1:length(argnames) )
argk[j]<-which(names(qq)==argnames[1] )
arglist<-list()
for(j in 1:length(qq) )
if(!is.na(argk[j])) arglist[[names(qq)[j]]]<-qq[[j]]
colvar<- do.call(coleqn,arglist)
} else {
# the input is just an expression (string), not a function
colvar <- eval(parse(text=coleqn))
}
结果是一个由表达式或刚创建的函数生成的对象,使用main函数内部的变量(未在此片段中显示)