Why does curve not seem to work with elements extracted from a list?
Consider two seemingly identical functions, but built differently:
a <- function(value){
function(x) x + value
}
m <- lapply(1:3, a)
f <- a(1)
all.equal(f, m[[1]])
#[1] TRUE
curve works for f, but not m[[1]]:
> curve(m[[1]])
Error in curve(m[[1]]) :
'expr' must be a function, or a call or an expression containing 'x'
But it works if the object is extracted before:
d <- m[[1]]
curve(d)
Is there a reason for it?
curve() is a "magic" function that tries to interpret its input as an expression when possible; it doesn't always work.
#user2554330 comments that curve() is expecting (from ?curve):
The name of a function, or a call or an expression written as a function of x which will evaluate to an object of the same length as x.
Instead, m[[1]] is an expression that evaluates to a function. In contrast, d is the name of a function. You can get what you want using curve(m[[1]](x)) which makes the input an expression written as a function of x.
In the code below, R looks at the expression passed to curve() and asks whether is.name(sexpr) is TRUE. This test passes for f but fails for m[[1]] (if you want to test it outside of the function context, you need to compare is.name(quote(f)) and is.name(quote(m[[1]])).
Weirdly enough, plot(m[[1]]) does work (it calls plot.function(), which calls curve() with different arguments internally).
sexpr <- substitute(expr)
if (is.name(sexpr)) {
expr <- call(as.character(sexpr), as.name(xname))
}
else {
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in%
all.vars(sexpr)))
stop(gettextf("'expr' must be a function, or a call or an expression containing '%s'",
xname), domain = NA)
expr <- sexpr
}
Related
I was trying to create a function to derive an expression and the command gives the error below.
Can anybody help me ?
derivada<- function(x){
expression(x)
z <- D(x,"x")
print(z)
}
derivada(x^2)
Error in D(x, "x") : object 'x' not found
Something like
derivada <- function(x) D(substitute(x), "x")
derivada(x^2)
## 2 * x
the main point here is that substitute(x) captures the expression that was passed as an argument without attempting to evaluate it. (Dealing with expressions and controlling when they get evaluated is tricky.)
I had the function return an expression (which then gets auto-printed) rather than printing the result
I didn't use curly brackets because the function only takes one expression (although arguably using curly brackets anyway would be better practice)
f <- function(x) {
a <- 1
x
}
f(ls())
In the above code, the call to f(ls()) will print out the variables in the global environment.
But:
f <- function(x) {
a <- 1
x()
}
f(ls)
will print out the variables in the environment of the function f, namely "a" and "x".
In the first case you pass the results of ls() - which is a vector of all objects in the environment. And your function just prints what was passed with x, namely - the results of ls().
In the second case you pass a function and the function get's executed within the function body.
Basically you can think about the first version of your call as:
x <- ls()
f(x)
As an additional example: look at the difference between print(ls()) and print(ls).
I have got the following problem. I am trying to compute a function like:
derivation <- function(function, number) {
derivation <- deriv(~function, "x")
return(derivation(number))
}
For example:
derivation(x^2, 3) {
derivation <- 2*x
return(2*3)
}
I don't care if I have to put the function in the beginning in braces or as an expression. The variable will always be x. Also be open to use D.
One possibility:
f <- function(fun,val) {
expr <- substitute(fun)
d <- deriv(expr,"x",function.arg=TRUE)
g <- attr(d(val),"gradient")
return(g)
}
f(x^2,3)
substitute() converts the argument fun to an expression without evaluating it
deriv(...,function.arg=TRUE) returns a function that computes the value and includes the derivative as an attribute
d(val) calls the function
attr(.,"gradient") extracts the gradient
If you want to return both the function value and its gradient (as a two-element vector), you could use
r <- d(val)
return(c(c(r),attr(r,"gradient"))
in the function (the internal c(r) drops the attributes from r).
I've been fascinated lately by Hadley Wickhams Non-standard Evaluation examples in R, but I'm not sure what I want to do is possible.
I want to have a closure-based environment where you pass expressions that get evaluated (in NSE ways), similar to how subset works. The problem though, is that to do so I think I need to fundamentally change how arguments are passed.
For example,
g <- function(setup_stuff){
function(x) {
substitute(x)
}
}
will give me the expression assigned to x if I so something like:
test <- g("Setup stuff")
test(1:10)
# 1:10
Similarly, I can do something like:
g <- function(setup_stuff){
function(x) {
sys.call(x)
}
}
Which will usually give me kind of what I'm looking for--a completely unevaluated argument list:
test <- g("setup variables")
test(1:10)
# test(1:10)
But this all relies on the idea that I pass variables the "standard" way, by delimiting assigned parameters with commas. I want to have something like:
g <- function(setup_stuff){
function(...) {
# Capture named expression(s) before evaluation
substitute(...)
}
}
Such that, for example, I can evaluate the arguments in a based on their named and the operators passed in, for example I've been trying to overload the logical operator &, but I just receive an error before the function to do NSE is even called:
test <- g("Setup stuff")
test(a=1 & b=2)
# > test(a=1 & b=2)
# Error: unexpected '=' in "test(a=1 & b="
I know I could probably do half-accomplish this by overloading the '&' and the '=' operator for some specific class, and just return the unevaluated call, but then a and b would need to be objects of that class, but I was wondering if I was missing something that someone can easily see?
For the moment, at least, this is an exercise in learning for me, so the actual functions or their complexity is not the issue. Suppose I write a function whose argument list includes some input variables and a function name, passed as a string. This function then calculates some variables internally and "decides" how to feed them to the function name I've passed in.
For nonprimitive functions, I can do (for this example, assume non of my funcname functions have any arguments other than at most (x,y,z). If they did, I'd have to write some code to search for matching names(formals(get(funcname))) so as not to delete the 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 nice thing is, even if the function funcname will execute without error even if it doesn't use x, y or z (so long as there are no other args that don't have defaults) .
The problem with "primitive" functions is I don't know any way to find or modify their formals. Other than writing a wrapper, e.g. foosin <-function(x) sin(x), is there a way to set up my foo function to work with both primitive and nonprimitive function names as input arguments?
formals(args(FUN)) can be used to get the formals of a primitive function.
You could add an if statement to your 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
#
#
# $...
Building on Richard S' response, I ended up doing the following. Posted just in case anyone else ever tries do things as weird as I do.
EDIT: I think more type-checking needs to be done. It's possible that coleqn could be
the name of an object, in which case get(coleqn) will return some data. Probably I need
to add a if(is.function(rab)) right after the if(!is.null(rab)). (Of course, given that I wrote the 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'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))
}
The result is an object generated either by the expression or the function just created, using variables internal to the main function (which is not shown in this snippet)