How to get forms of a primitive function?

At the moment, at least, this is an exercise in learning for me, so the actual functions or their complexity is not a problem. Suppose I write a function whose argument list contains some input variables and the name of the function passed as a string. This function then calculates some variables inside and "decides" how to pass them the name of the function in which I passed.

For non-primitive functions, I can do (for this example, suppose that not my funcname functions have any arguments other than (x,y,z) . If they did, I would have to write code to search for names(formals(get(funcname))) so as not to remove other arguments):

 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) } 

And the best part is, even if the funcname function is executed without errors, even if it does not use x , y or z (as long as there are no other arguments, t have default values).
The problem with the "primitive" functions is that I do not know how to find or change their formats. Besides writing a wrapper like foosin <-function(x) sin(x) , is there a way to set my foo function to work with both primitive and non-primitive function names as input arguments?

+6
source share
2 answers

formals(args(FUN)) can be used to get the forms of a primitive function.

You can add an if to an existing function.

 > 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 # # # $... 
+3
source

Based on Richard C.'s answer, I ended up doing the following. It is written just in case when someone else is trying to do something strange, like me.

EDIT: I think we need more type checking. It is possible that coleqn might be the name of an object, in which case get(coleqn) will return some data. I guess I need to add if(is.function(rab)) right after if(!is.null(rab)) . (Of course, given that I wrote a function for my own needs, if I was stupid enough to pass an object, I deserve what I get :-)).

 # "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 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)) } 

The result is an object generated either by an expression or by a function just created using variables internal to the main function (which are not shown in this fragment)

+1
source

Source: https://habr.com/ru/post/975662/


All Articles