How does lazy evaluation binds variable (in R) - r

I'm fairly new to R and I just noticed that the first call to a function seems to bind its environment parameters. How does this work ? (Or how is it it called, so I can look it up in the doc).
E.g.:
make.power <- function(n)
{
pow <- function(x)
{
x^n
}
}
i <- 3
cube <- make.power(i)
# print(cube(3)) # uncommenting this line change the value below
i <- 2
square <- make.power(i)
print(cube(3)) # this value changes depending on whether cube(3) was called before.
print(square(3))
I'm looking for a sample explanation of what's going on, or just the name of this feature, so I can look it up.
Thanks !

Related

creating list of outputs from a function

I would like to know how can I list the outputs of my function (it prints out vectors) so that I am able to know how many steps did it require until finding the optimal solution.
I have the following code and am just wondering what should I do at the end so that when printing out the vectors, it enumerates them one at a time as well. I am new to Rstudio and do see that some operations that have to do with matrices are not common in other programming languages.
I should say that I have already defined another function such as "gradient", but my concern is about the enumeration of the outputs for this particular function.
Sd=function(b0,epsilon=1e-5){
while (norm(gradient(b0))>epsilon) {
num1=(t(b0)%*%Q%*%gradient(b0)-t(y)%*%X%*%gradient(b0))/(t(gradient(b0))%*%Q%*%gradient(b0))
num2=norm(num1)
step=num2*gradient(b0)
b0=b0-step
print(t(b0))
}
}
Thank you for any help I can get.
Here's a generic answer that will show you how to approach this. Without access to your custom functions I can't give a more direct answer. It's generally helpful to give a minimal reproducible example.
That said, my basic suggestion is to use a counter variable, increment it once each loop, and include that in your printed output.
Here's a simplified example that's based on your code, but the only operation we're doing is taking repeated square roots. Note that the arrow operator <- is the best practice for assigning values. (I promise you get used to it!)
# set up a generic function for this minimal example
get_value <- function(x){
return (sqrt(x))
}
my_function <- function(b0, epsilon = 1.1){
# set up a counter variable
i <- 0
# our main loop
while (get_value(b0) > epsilon) {
# increment the counter
i <- i + 1
# do calculations
num1 <- get_value(b0)
# update our current solution
b0 <- num1
# print a message to the console with the counter and the value
message(paste0("Iteration: ",i,"\n",
"b0: ", b0))
}
# print a final message to the console when we stop
message(paste0("Final Iteration: ",i,"\n",
"Final b0: ", b0))
}
my_function(2)

Saving Matrix within Function to Parent Environment

So I currently have several functions where I want to modify a matrix that was created outside the function, in order to use it as a counting variable for things that happen inside the function. The matrix is named cost_counter, and I want to add to it when certain events occur inside of multiple functions. However, I'd like the solution to still be able to be used in foreach() and be parallelizable.
I know that using <<- is not recommended, however I can't figure out how to use assign() to modify an existing matrix. Example code is below. I've defined the variable cost_counter at the beginning. The function below goes on for longer, but I'm just including the first part for an example of what is happening.
cost_counter <<- matrix(0,nrow = 2, ncol = 12*15)
I0 <- function(){
if (screen[i] == 1){
cost_counter[2,ages[i]] <<- 1 + cost_counter[2,ages[i]] + 1
if(HIV[i] == 1){
if(ages[i] > 35){
if(pv[(i-min_i+1),1] < (1-specP3)){
cost_counter[1,ages[i]] <<- cost_counter[1,ages[i]] + 1
if(contact[i] == 1){return(c(5,0))}
}
}
When I run, error message simply says
"Error in cost_counter[2, ages[i]] <<- cost_counter[2, ages[i]] + 1 :
object 'cost_counter' not found"
I would just like to be able to modify the matrix, and for it to be recognized.
Any help would be appreciated. Thanks!
just at the end f the function re assign the function's matrix to the global env using:
cost_counter <<- cost_counter

Why does repeating a loop change the results of looped optimization?

My original function embodies several optimize() functions, for which I get different results when I apply the function the first time vs. second time.
I tried this but I made sure that the returned value is one-dimensional.
fn = function(A,P){
l_fn = function(x) {
L <- x[1]
-((A*L*P)-(P*L^2)) # -1 because optimize-function finds minimum
}
l_opt <- as.numeric(optimize(l_fn,c(0,1000))[2]) # get objective output
return(l_opt)
}
f <- data.frame(x=c(10:20))
for (i in 1:length(f)) { # run this part 2 times!
f$test <- sin(f$x) # this is how I expect a function to behave
f$out[i] <- fn(f$x[i],100)
}
running the code the first time produces f$out that are all equal (weird). running the for loop again changes f$out, eventhough the input parameters remain the same! How is that possible?

Immutable Objects in R - what happens here under the hood?

I am a little bit confused. I learned to never grow a vector because we do not want to create a new copy of an object every time.
# Bad
start <- Sys.time()
vector1 <- vector()
for(i in 1:100000000) {
vector1[i] <- i
}
end <- Sys.time()
print(end - start)
Time difference of 17.06454 secs
# Good
vector2 <- vector(length = 100000000)
start <- Sys.time()
for(i in 1:100000000) {
vector2[i] <- i
}
end <- Sys.time()
print(end - start)
Time difference of 4.50159 secs
The results tend to prove this correct, however, for example I read here: http://adv-r.had.co.nz/Functional-programming.html something like this: "Mutable state is normally hard because every time it looks like you’re modifying an object, you’re actually creating and then modifying a copy."
So am I not creating a copy everytime I store a new value inside the vector in example 2? Should this not normally not be even slower, because each iteration a vector of size 100.000.000 gets copied?
What do I not understand here?
The section you were reading was in the context of a function. If you check out the section on memory, you'll see
What happens to x in the following code?
x <- 1:10
x[5] <- 10
There are two possibilities:
R modifies x in place.
R makes a copy of x to a new location, modifies the copy, and then uses the name x to point to the new location.
It turns out that R can do either depending on the circumstances. In the example above, it will modify in place.
So, for what you're doing, you are modifying in place. You would not be modifying in place for something like this:
f <- function(vec) {
for(i in 1:length(vec)) {
vec[i] <- i
}
return(vec)
}
You would be creating a local (to the function) copy of vec before modying the copy in place. That's what the Hadley quote was talking about.

Naming different variables and using i to subset a file

I want to go through a vector, name all variables with i and use i to subset a larger file.
Why this does not work?
x <- c(seq(.1,.9,.1),seq(.9,1,.01))
doplot <- function(y)
{
for (i in unique(y))
{
paste("f_", i, sep = "") <- (F_agg[F_agg$Assort==i,])
}
}
doplot(x)
There are several problems here. First of all, on the left hand side of <- you need a symbol (well, or a special function, but let's not get into that now). So when you do this:
a <- "b"
a <- 15
then a will be set to 15, instead of first evaluating a to be b and then set b to 15.
Then, if you create variables within a function, they will be (by default) local to that function, and destroyed at the end of the function.
Third, it is not good practice to create variables this way. (For details I will not go into now.) It is better to put your data in a named list, and then return the list from the function.
Here is a solution that should work, although I cannot test it, because you did not provide any test data:
doplot <- function(y) {
lapply(unique(y), function(i) {
F_agg[F_agg$Assort == i, ]
})
}

Resources