How to test modified functional forms

In my never-ending quest to break things, consider the following questions:

gbar<-function(x,y,x,a) x+2*y-4*a Error: repeated formal argument 'x' on line 1 

R correctly checks my specific function for illegal formats.

But if I scold manually:

  ffoo<-function(x,y,a) x+2*y-4*a formals(ffoo)<-c(x=7, formals(ffoo)) 

Then I will only find out under certain circumstances that something is invalid. ffoo(3,4,5,6) will execute correctly (although probably not giving me the answer I was expecting), like ffoo(y=3,a=2) ; whereas ffoo(x=5,y=3,a=2) will throw an error about ambiguous argument names.

So: is there a base-R or an extended utility package with the sanity check function on the formals existing function?

+5
source share
1 answer

Edit:

If you just want to check for duplicate arguments, you can do this:

 any(duplicated(names(formals(ffoo)))) # [1] TRUE 

As Hadley mentions in his second comment below, dput() does not guarantee you a good / complete representation of the function, so there may be functions for which the approach described in my original answer (bottom left) fails.


Original answer:

As outlined in the C code that Andrie points to , this is apparently a test of what R does when parsing (not evaluating) call function() . This is why you were able to get around validation with your call to formals<- , and why the following (for example) also avoids validation. In both cases, the function is changed / created without parsing the call to function() .

 eval(call("function", formals(ffoo), body(ffoo))) # function (x = 7, x, y, a) # x + 2 * y - 4 * a 

The R parsing mechanism is usually not displayed in user-visible R-functions, so I would not assume that there is no ready-made R-function for this check. However, you can perform the same set of checks that R performs when you send an expression, or enter it on the command line, converting a function definition into its character representation, and then trying to reanalyze it yourself.

Here's a general idea:

 parse(text = capture.output(dput(ffoo))) # Error in parse(text = capture.output(dput(ffoo))) : # repeated formal argument 'x' on line 1 

To wrap the check as a function, do something like this:

 isParseableFunction <- function(x) { tryCatch(is.function(x) & is.expression(parse(text = capture.output(dput(x)))), error = function(e) FALSE) } isParseableFunction(data.frame) # [1] TRUE isParseableFunction(mean) # [1] TRUE isParseableFunction(ffoo) # [1] FALSE isParseableFunction(99) # [1] FALSE 
+4
source

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


All Articles