I have a function f(x) where the default value of x is 2. The function returns the square.
f <- function(x = 2){
return(x^2)
}
I want to check in the function if the user gives value to x. Even if the value given is 2, I want to know.
Perhaps this is the equivalent code of what I want.
f <- function(x){
if(!missing(x)) print("User did not give value to x")
if(missing(x)) x <- 2
return(x^2)
}
I want to do something similar by setting the default value of x to 2 (not NULL also). Is it possible?
You may use match.call. In this case we could do
f <- function(x = 2) {
if(is.null(match.call()$x))
print("Nothing")
x^2
}
f()
# [1] "Nothing"
# [1] 4
f(2)
# [1] 4
f(x = 2)
# [1] 4
Related
I fear I get something really wrong. The basics are from here
and a basic (minimal) example is understood (I think) and working:
fun.default <- function(x) { # you could add further fun.class1 (works)...
print("default")
return(x[1] + x[2])
}
my_fun <- function(x) {
print("my_fun")
print(x)
res <- UseMethod("fun", x)
print(res)
print("END my_fun...")
return(res)
}
x <- c(1, 2)
my_fun(x)
However, if I want to add parameters, something goes really wrong. Form the link above:
Once UseMethod has found the correct method, it’s invoked in a special
way. Rather than creating a new evaluation environment, it uses the
environment of the current function call (the call to the generic), so
any assignments or evaluations that were made before the call to
UseMethod will be accessible to the method.
I tried all variants I could think of:
my_fun_wrong1 <- function(x, y) {
print("my_fun_wrong1")
print(x)
x <- x + y
print(x)
res <- UseMethod("fun", x)
print(res)
print("END my_fun_wrong1...")
return(res)
}
x <- c(1, 2)
# Throws: Error in fun.default(x, y = 2) : unused argument (y = 2)
my_fun_wrong1(x, y = 2)
my_fun_wrong2 <- function(x) {
print("my_fun_wrong2")
print(x)
x <- x + y
print(x)
res <- UseMethod("fun", x)
print(res)
print("END my_fun_wrong2...")
return(res)
}
x <- c(1, 2)
y = 2
# Does not throw an error, but does not give my expetced result "7":
my_fun_wrong2(x) # wrong result!?
rm(y)
my_fun_wrong3 <- function(x, ...) {
print("my_fun_wrong3")
print(x)
x <- x + y
print(x)
res <- UseMethod("fun", x)
print(res)
print("END my_fun_wrong3...")
return(res)
}
x <- c(1, 2)
# Throws: Error in my_fun_wrong3(x, y = 2) : object 'y' not found
my_fun_wrong3(x, y = 2)
Edit after answer G. Grothendieck: Using fun.default <- function(x, ...) I get
Runs after change, but I don't understand the result:
my_fun_wrong1(x, y = 2)
[1] "my_fun_wrong1"
[1] 1 2
[1] 3 4 # Ok
[1] "default"
[1] 3 # I excpect 7
As before - I don't understand the result:
my_fun_wrong2(x) # wrong result!?
[1] "my_fun_wrong2"
[1] 1 2
[1] 3 4 # Ok!
[1] "default"
[1] 3 # 3 + 4 = 7?
Still throws an error:
my_fun_wrong3(x, y = 2)
[1] "my_fun_wrong3"
[1] 1 2
Error in my_fun_wrong3(x, y = 2) : object 'y' not found
I think, this question is really useful!
fun.default needs ... so that the extra argument is matched.
fun.default <- function(x, ...) {
print("default")
return(x[1] + x[2])
}
x <- c(1, 2)
my_fun_wrong1(x, y = 2)
## [1] "my_fun_wrong1"
## [1] 1 2
## [1] 5 6
## [1] 3
Also, any statements after the call to UseMethod in the generic will not be evaluated as UseMethoddoes not return so it is pointless to put code after it in the generic.
Furthermore, you can't redefine the arguments to UseMethod. The arguments are passed on as they came in.
Suggest going over the help file ?UseMethod although admittedly it can be difficult to read.
Regarding the quote from ?UseMethod that was added to the question, this just means that the methods can access local variables defined in the function calling UseMethod. It does not mean that you can redefine arguments. Below ff.default refers to the a defined in ff.
a <- 0
ff <- function(x, ...) { a <- 1; UseMethod("ff") }
ff.default <- function(x, ...) a
ff(3)
## [1] 1
I have a problem with a function of the following kind:
fun.name <- function(x,y) {
a<-x
b<-y
for (i in c(a, b)){
i<-i+1
print (i)
}
print(a)
print(b)
}
fun.name(1, 2)
The result is
[1] 2
[1] 3
[1] 1
[1] 2
The same result is obtained if I do not create any a and b and I simply keep x and y ( fun.name <- function(x,y) { for (i in c(a, b))...).
I cannot understand this behavior.
What I wanted was a function which adds one to every arguments and prints the results. Why does not the loop modify the variables a and b when it is defined within the function? I guess it is a problem of environments, and that I have not understood the nature of a function arguments.
Thank you for any suggestions.
I actually expect to see your current output. Here is your code, formatted, with explanations as comments:
fun.name <- function(x,y) {
a <- x
b <- y
for (i in c(a, b)) { # i in (1, 2)
# first iteration: i = 2, print 2
# second iteration: i = 3, print 3
i <- i+1
print(i)
}
print(a) # prints 1 (a was only assigned once)
print(b) # prints 2 (same reason as above)
}
fun.name(1, 2)
There are no changes to a and b after their initial assignments inside the function. But, even if there were changes, the variables a and b would not even be visible outside the scope of the function.
I have a global variable x and want to build a function f that returns the value of x at the time the function is created. Example:
x <- 5
f <- function() return(x)
f()
> 5
x <- 10
f()
> 10 # Should return 5
I want a function that always return 5 (or whatever the value of x is at the time of function creation) without using another global variable. Is that possible?
Still another option using body:
f<-`body<-`(function() {},value=x)
Example:
x<-10
f<-`body<-`(function() {},value=x)
f()
#[1] 10
x<-100
f()
#[1] 10
Digging the source code of body, here is an even cleaner solution equivalent to the above using as.function:
f<-as.function(list(x))
This is not possible with global variables alone. When a function is defined, none of the variables in the function body are actually evaluated till the function is called. What you want seems to be a closure to hold the value at the time of creation. Instead write a function that returns a function
x <- 5
getfun <- function() {z<-x; function() return(z)}
f <- getfun()
x<- 10
g <- getfun()
f()
# [1] 5
g()
# [1] 10
Or even better, don't implicitly use global variables. Create a function that takes a certain set of parameters and returns a new function
returnVal <- function(x) {force(x); function() return(x)}
f<-returnVal(5)
g<-returnVal(10)
f()
# [1] 5
g()
# [1] 10
1) This saves the value of x the first time f is called and then uses that value of x even if x has been changed the next time f is called. Create f in a local environment and have f place x in that environment. If x was not previously there it will now be. If it was previously there then it will be the x retrieved and placed back. The result is that the first x encountered will always be used.
f <- local(function() {
p <- parent.env(environment())
p$x <- x
x
})
x <- 5
f()
## [1] 5
x <- 10
f()
## [1] 5
2) In comments #Konrad and #Frank have suggested the following variation in which we remove the assignment from f and put it in the local.
There is one difference from the viewpoint of the user of the function. This instantiates the value of x at the time the function is defined whereas (1) instantiates x the first time that the function is called and that might be an advantage if you want to separate the definition and the instantiation.
x <- 5
f <- local({ x <- x; function() x })
f()
## [1] 5
x <- 10
f()
## [1] 5
3) We can also consider completely separating the function from the instantiation. This would also allow re-initialization at any time by calling e$init() again.
e <- local({
init <- function() {
p <- parent.env(environment())
p$x <- x
}
run = function() x
environment()
})
x <- 5
e$init()
e$run()
## [1] 5
x <- 10
e$run()
## [1] 5
4) (3) could be implemented using a variety of object oriented frameworks such as Reference Classes, proto or R6. In proto it would be like this:
library(proto)
p <- proto(init = function(.) .$x <- x, run = function(.) x)
x <- 5
p$init()
p$run()
## [1] 5
x <- 10
p$run()
## [1] 5
Below is a contrived example of passing a parameter to a returned function. I would like to have the returned function evaluate param to 2, and in fact, that's what it does!!
However, how does this work? When I print the function, it shows "param" and not "2". But when I debug(), I confirm that param is in fact 2.
f <- function(x, param = 2) {
my_cdf <- ecdf(x)
function(new_x) {
my_cdf(new_x) * param
}
}
g <- f(1:10)
g
# > function(new_x) {
# > my_cdf(new_x) * param
# > }
As param is not defined in the function in which it is used, param is looked up in the environment in wihch the function that uses it was defined and param = 2 in that environment. This is referred to as lexical scoping.
If you want to have param actually substituted into the function then try substitute like this:
f <- function(x, param = 2) {
my_cdf <- ecdf(x)
F <- function(new, x)
my_cdf(new_x) * param
body(F) <- do.call("substitute", list(body(F), list(param = param)))
F
}
f(1:10)
This chapter from Advanced R has greater detail on what is happening.
A few examples from that chapter:
as.list(environment(g))
# $my_cdf
# Empirical CDF
# Call: ecdf(x)
# x[1:10] = 1, 2, 3, ..., 9, 10
#
# $x
# [1] 1 2 3 4 5 6 7 8 9 10
#
# $param
# [1] 2
library(pryr)
unenclose(g)
# function (new_x)
# {
# (function (v)
# .approxfun(x, y, v, method, yleft, yright, f))(new_x) * 2
# }
When providing a default argument to an R function, this argument is evaluated when first used in the function. How is it possible to evaluate default argument earlier in an elegant way? Example:
f <- function(x, y = 2 * x)
{
if(x < 0) x = 10
y
}
f(1) ## Returns 2
f(-1) ## Returns 20 but I would like it to return -2
Thanks
The answer wasn't to hard to find. The function 'force' does the trick:
f <- function(x, y = 2 * x)
{
force(y)
if(x < 0) x = 10
y
}
f(1) ## Returns 2
f(-1) ## -2