learning R with, The Art of R Programming.
Until about 1/2 through he has simply defined a new function like this:
fnc=function(a,b){
return(a) }
But now is doing stuff like this:
> g
function() {
t <- function(x) return(x^2)
return(t)
}
> g()
function(x) return(x^2)
Is this the same as saying:
g=function(x) return(x^2)
What is the g in the first block?
Running the exact code he has does not work for me, it just prints out what I had in g.
Thank you everyone.
If your code transposition from book to SO is accurate, the author is defining a function that returns a function:
g <- function() {
t <- function(x) return(x^2)
return(t)
}
We can see that if we execute it:
g()
## function(x) return(x^2)
## <environment: 0x7fd7c5aa7d10>
And, we can use the fact that it returns a function by passing in a parameter to what it returns either this way:
g()(10)
## 100
or this way:
squareIt <- g()
squareIt(10)
## 100
Related
I have a function that looks like
my_function <- function(object)
{
# code goes here
}
I'd like the function (among other things) to print the name of the argument (as passed to the function). So if my function call is:
xxx <- my_function(my_object)
then I'd like to know how to get the function to print out the string "my_object".
Can anyone help please?
A more R-ish solution would be to use substitute (get substitute for obj) in combination with deparse (cast symbol to string):
my_function <- function(obj) {deparse(substitute(obj))}
General R metaprogramming rule: prefer substitute!
my_function(my_object)
## [1] "my_object"
I would suggest next approach which is closer to what you want. For sure you could modify it to obtain other outputs:
#Function
my_function <- function(x)
{
as.character(eval(parse(text=enquo(x)))[2])
}
#Apply
my_function(x = my_object)
Output:
[1] "my_object"
An improvement thanks to #MrFlick is next:
#Function
my_function <- function(x)
{
rlang::as_label(rlang::enquo(x))
}
#Apply
my_function(x = my_object)
Which produces same output with a more elegant style in the function:
[1] "my_object"
To display the entire call use match.call like this:
f <- function(x) { print(match.call()); x }
f(pi)
## f(x = pi)
## [1] 3.141593
IF it is desired to display the call just for debugging without modifying the function itself then use trace:
g <- function(x) x # test function
trace(g)
g(pi)
## trace: g(pi)
## [1] 3.141593
I recently (very) started looking into creating S3 functions in R. I am working in a function where I foresee having common operations between different methods. Not sure how this should be done. For example:
myfun <- function (x) {
UseMethod("myfun")
}
myfun.numeric <- function(x) {
a<-x+5
b<-a^2
c<-b+4
d<-c-3
d
}
myfun.character <- function(x) {
a<-as.numeric(x)+9
b<-a^2
c<-b+4
d<-c-3
d
}
myfun("3")
myfun(3)
The function at this time is not too long. I guess technically I can have a function that perform the part represented by letter "a" then have a common function that perform steps "b", "c", and "d". In some cases the functions could be quite short and having an additional function seems not to be the best practice. What is usually done in cases like this?
Here are two possibilities. There is some danger in using the default method since it might get invoked in unanticipated situations so the common function seems more reliable but either would work in the example you show.
1) default method Put the common code in the default method and use NextMethod().
myfun <- function (x) UseMethod("myfun")
myfun.numeric <- function(x) {
x<-x+5
NextMethod()
}
myfun.character <- function(x) {
x <-as.numeric(x)+9
NextMethod()
}
myfun.default <- function(x) {
b<-x^2
c<-b+4
d<-c-3
d
}
myfun("3")
myfun(3)
2) common function Alternately just put the common code in a separate function called common, say, and call it.
myfun <- function (x) UseMethod("myfun")
myfun.numeric <- function(x) {
y <-x+5
common(y)
}
myfun.character <- function(x) {
y <-as.numeric(x)+9
common(y)
}
common <- function(x) {
b<-x^2
c<-b+4
d<-c-3
d
}
myfun("3")
myfun(3)
I have below function. I cannot alter the function in any way except the first block of code in the function.
In this simple example I want to display apply some function on returning object.
The point is the name of variable returned by function may vary and I'm not able to guess it.
Obviously I also cannot wrap the f function into { x <- f(); myfun(x); x }.
The below .Last.value in my on.exit call represents the value to be returned by f function.
f <- function(param){
# the only code I know - start
on.exit(if("character" %in% class(.Last.value)) message(print(.Last.value)) else message(class(.Last.value)))
# the only code I know - end
# real processing of f()
a <- "aaa"
"somethiiiing"
if(param==1L) return(a)
b <- 5L
"somethiiiing"
if(param==2L) return(b)
"somethiiiing"
return(32)
}
f(1L)
# function
# [1] "aaa"
f(2L)
# aaa
# [1] 5
f(3L)
# integer
# [1] 32
Above code with .Last.value seems to be working with lag (so in fact not working) and also the .Last.value is probably not the way to go as I want to use the value few times like if(fun0(x)) fun1(x) else fun2(x), and because returned value might be a big object, copy it on the side is also bad approach.
Any way to use on.exit or any other function which can help me to run my function on the f function results without knowing result variable name?
In a similar way to how you are modifying the function, you could easily wrap it as well. Here's a reproducible example.
library(data.table)
append.log<-function(x) {
cat(paste("value:",x,"\n"))
}
idx.dt <- data.table:::`[.data.table`
environment(idx.dt)<-asNamespace("data.table")
idx.wrap <- function(...) {
x<-do.call(idx.dt, as.list(substitute(...())), envir=parent.frame())
append.log(if(is(x, "data.table")) {
nrow(x)
} else { NA })
x
}
environment(idx.wrap)<-asNamespace("data.table")
(unlockBinding)("[.data.table",asNamespace("data.table"))
assign("[.data.table",idx.wrap,envir=asNamespace("data.table"),inherits=FALSE)
dt<-data.table(a=1:10, b=seq(2, 20, by=2), c=letters[1:10])
dt[a%%2==0]
Since R 3.2.0 it is fully possible, thanks to new function returnValue.
Working example below.
f <- function(x, err = FALSE){
pt <- proc.time()[[3L]]
on.exit(message(paste("proc.time:",round(proc.time()[[3L]]-pt,4),"\nnrow:",as.integer(nrow(returnValue()))[1L])))
Sys.sleep(0.001)
if(err) stop("some error")
return(x)
}
dt <- data.frame(a = 1:5, b = letters[1:5])
f(dt)
f(dt, err=T)
f(dt)
f(dt[dt$a %in% 2:3 & dt$b %in% c("c","d"),])
How can I get the current function within a function for recursive applying? Here is a trivial example:
myfun <- function(x) {
if(is.list(x)){
lapply(x, myfun)
} else {
length(x)
}
}
I would like to make it anonymous instead, however I don't know how to tell lapply to use the current function when it has no name. I tried Recall but that doesn't work:
(function(x) {
if(is.list(x)){
lapply(x, Recall)
} else {
length(x)
}
})(cars)
Also match.call()[[1]] doesn't help for anonymous functions.
It is sys.function(0) , for example to compute the square of a list recursively :
(function(x) {
if(length(x)>2){
lapply(x,sys.function(0))
} else {
x^2
}
})(list(1,2,3))
[[1]]
[1] 1
[[2]]
[1] 4
[[3]]
[1] 9
What you are looking for is, I think, sys.function:
> (function() print(sys.function(1)))()
function() print(sys.function(1))
Recall actually says:
local for another way to write anonymous recursive functions.
The idea is that you define the name locally:
local(myfun <- function(...) { ... myfun(...) ... })
and it is not defined outside.
I am constructing an approximating function recursively (adaboost). I would like to create the resulting learning function along the way (not to apply the approximation directly to my test data but keep the function that leads to it)
unfortunately, it seems that R updates the value to which a variable name refers to long after it is used.
#defined in plyr as well
id <- function(x) {x}
#my first classifier
modelprevious <- function(inputx, k) { k(0)}
#one step of my superb model
modelf <- function(x) 2*x #for instance
#I update my classifier
modelCurrent <- function(inputx, k)
{ modelprevious(inputx, function(res) {k(res + modelf(inputx))})}
#it works
modelCurrent(2,id) #4
#Problem
modelf <- function(x) 3*x
modelCurrent(2,id) #6 WTF !!
The same function with the same argument return something different, which is quite annoying !
So how is it possible to capture the value represented by modelf so that the resulting function only depends on its argument at the time of the binding, and not of some global state ?
Given that problem I dont see how one can do a recursive function building in R if one can not touch local variable, apart going through ugly hacks of quote/parse
You need a factory:
modelCurrent = function(mf){
return(function(inputx,k){
modelprevious(
inputx,
function(res){
k(res+mf(inputx))
} # function(res)
) # modelprevious
} # inner function
) # return
} # top function
Now you use the factory to create models with the modelf function that you want it to use:
> modelf <- function(x) 2*x
> m1 = modelCurrent(modelf)
> m1(2,id)
[1] 4
> modelf <- function(x) 3*x
> m1(2,id) # no change.
[1] 4
You can always make them on an ad-hoc basis:
> modelCurrent(modelf)(2,id)
[1] 6
and there you can see the factory created a function using the current definition of modelf, so it multiplied by three.
There's one last ginormous WTF!?! that will hit you. Watch carefully:
> modelf <- function(x) 2*x
> m1 = modelCurrent(modelf)
> m1(2,id)
[1] 4
>
> m1 = modelCurrent(modelf) # create a function using the 2* modelf
> modelf <- function(x) 3*x # change modelf...
> m1(2,id) # WTF?!
[1] 6
This is because when the factory is called, mf isn't evaluated - that's because the inner function isn't called, and mf isn't used until the inner function is called.
The trick is to force evaluation of the mf in the outer function, typically using force:
modelCurrent = function(mf){
force(mf)
return(function(inputx,k){
modelprevious(
inputx,
function(res){
k(res+mf(inputx))
} # function(res)
) # modelprevious
} # inner function
) # return
} # top function
This has lead me to premature baldness, because if you forget this and think there's some odd bug going on, and then try sticking print(mf) in place to see what's going on, you'll be evaluating mf and thus getting the behaviour you wanted. By inspecting the data, you changed it! A Heisenbug!