How Does R Handle Object in Function Call

How does R handle object in function call?

x is defined in the global environment, not in your function.

If you try to modify a non-local object such as x in a function then R makes a copy of the object and modifies the copy so each time you run your anonymous function a copy of x is made and its ith component is set to 4. When the function exits the copy that was made disappears forever. The original x is not modified.

If we were to write x[i] <<- i or if we were to write x[i] <- 4; assign("x", x, .GlobalEnv) then R would write it back. Another way to write it back would be to set e, say, to the environment that x is stored in and do this:

e <- environment()
sapply(1:10, function(i) e$x[i] <- 4)

or possibly this:

sapply(1:10, function(i, e) e$x[i] <- 4, e = environment())

Normally one does not write such code in R. Rather one produces the result as the output of the function like this:

x <- sapply(1:10, function(i) 4)

(Actually in this case one could write x[] <- 4.)

ADDED:

Using the proto package one could do this where method f sets the ith component of the x property to 4.

library(proto)

p <- proto(x = 1:10, f = function(., i) .$x[i] <- 4)

for(i in seq_along(p$x)) p$f(i)
p$x

ADDED:

Added above another option in which we explicitly pass the environment that x is stored in.

Apply a set of functions to an object

Some good answers already but throw in another option - build a pipe chain as a string then evaluate it. For example - for row 1 - eval(parse(text = "1 %>% rule1")) gives 2

eval_chain <- function(df) {
eval(parse(text = paste(c(df$data, unlist(strsplit(df$rules, ", "))), collapse=" %>% ")))
}

df$value <- sapply(1:nrow(df), function(i) df[i, ] %>% eval_chain)
# data rules value
# 1 1 rule1 2
# 2 2 rule1, rule2, rule3 125
# 3 3 rule3, rule2 28

What's the real meaning about 'Everything that exists is an object' in R?

The function is.object seems only to look if the object has a "class" attribute. So it has not the same meaning as in the slogan.

For instance:

x <- 1
attributes(x) # it does not have a class attribute
NULL
is.object(x)
[1] FALSE
class(x) <- "my_class"
attributes(x) # now it has a class attribute
$class
[1] "my_class"
is.object(x)
[1] TRUE

Now, trying to answer your real question, about the slogan, this is how I would put it. Everything that exists in R is an object in the sense that it is a kind of data structure that can be manipulated. I think this is better understood with functions and expressions, which are not usually thought as data.

Taking a quote from Chambers (2008):

The central computation in R is a function call, defined by the
function object itself and the objects that are supplied as the
arguments. In the functional programming model, the result is defined
by another object, the value of the call. Hence the traditional motto
of the S language: everything is an object—the arguments, the value,
and in fact the function and the call itself: All of these are defined
as objects. Think of objects as collections of data of all kinds. The data contained and the way the data is organized depend on the class from which the object was generated.

Take this expression for example mean(rnorm(100), trim = 0.9). Until it is is evaluated, it is an object very much like any other. So you can change its elements just like you would do it with a list. For instance:

call <- substitute(mean(rnorm(100), trim = 0.9))
call[[2]] <- substitute(rt(100,2 ))
call
mean(rt(100, 2), trim = 0.9)

Or take a function, like rnorm:

rnorm
function (n, mean = 0, sd = 1)
.Call(C_rnorm, n, mean, sd)
<environment: namespace:stats>

You can change its default arguments just like a simple object, like a list, too:

formals(rnorm)[2] <- 100
rnorm
function (n, mean = 100, sd = 1)
.Call(C_rnorm, n, mean, sd)
<environment: namespace:stats>

Taking one more time from Chambers (2008):

The key concept is that expressions for evaluation are themselves
objects; in the traditional motto of the S language, everything is an
object. Evaluation consists of taking the object representing an
expression and returning the object that is the value of that
expression.

So going back to our call example, the call is an object which represents another object. When evaluated, it becomes that other object, which in this case is the numeric vector with one number: -0.008138572.

set.seed(1)
eval(call)
[1] -0.008138572

And that would take us to the second slogan, which you did not mention, but usually comes together with the first one: "Everything that happens is a function call".

Taking again from Chambers (2008), he actually qualifies this statement a little bit:

Nearly everything that happens in R results from a function call.
Therefore, basic programming centers on creating and refining
functions.

So what that means is that almost every transformation of data that happens in R is a function call. Even a simple thing, like a parenthesis, is a function in R.

So taking the parenthesis like an example, you can actually redefine it to do things like this:

`(` <- function(x) x + 1
(1)
[1] 2

Which is not a good idea but illustrates the point. So I guess this is how I would sum it up: Everything that exists in R is an object because they are data which can be manipulated. And (almost) everything that happens is a function call, which is an evaluation of this object which gives you another object.

Calling objects from list

A very useful rule of thumb in R is:

If you find yourself using either assign() or get() in your code, it's a strong indicator that you are approaching the problem with the wrong tools. If you still think you should use those functions, think again. The tools that you are missing are most likely R lists and subsetting of lists.

(and tell everyone that you know about the above)

In your case, I would do something like:

library("rNMF")
[...]

var <- list()
varNF <- list()
for (i in 1:10) {
res <- rnmf(data, k = i, showprogress = FALSE)
var[[i]] <- res
varNF[[i]] <- (data - res$fit)^2
}

R - Get formals from call object

Well, a call does not have formals, only actual arguments... The difference being that a function like foo <- function(x, y, ..., z=42) can be called with actual arguments like foo(42, bar=13).

...But getting the arguments can be done like this:

a <- call('foo', a=42, 13)
as.list(a)[-1]
#$a
#[1] 42
#
#[[2]]
#[1] 13

...on the other hand, you can usually (not always) find the actual function and find the formals for it:

a <- quote(which(letters=='g'))
formals(match.fun(a[[1]]))
#$x
#
#$arr.ind
#[1] FALSE
#
#$useNames
#[1] TRUE

Here you'd need to add some error handling if the function can't be found (as with the call to foo above)...



Related Topics



Leave a reply



Submit