Is there some equivalent to express let expressions in r? As an example take this simple haskell code:
let x = 1 in x + 1
Many thanks in advance.
One equivalent would be a lambda function, which you can define and call in a single statement:
(function(x) x+1)(x = 1)
The first () part defines a function, while the second () part calls that function, supplying the value of 1 for the argument named x.
Here are a few:
x <- 100
# 1
with(list(x = 1), x + 1)
## [1] 2
# 2
local(x + 1, list(x = 1))
## [1] 2
# 2a
local({
x <- 1
x + 1
})
## [1] 2
# 3
eval(substitute(x + 1, list(x = 1)))
## [1] 2
# 4
library(wrapr)
let(c(x = "1"),
x + 1,
subsMethod = "stringsubs",
strict = FALSE)
## [1] 2
x
## [1] 100
Also there is an open issue in the lambda.r package to add let.
If the intent of this is to make x only available in that expression, environments could offer this capability:
#make an environment
myenv <- new.env()
#assign 1 to variable x in our environment
myenv$x <- 1
#evaluate the expression within our environment
with(myenv, x + 1)
#[1] 2
#x only works within our created environment and not on the global environment
#(i.e. the default environment when working on the console)
x + 1
#Error: object 'x' not found
As per #Roland 's comment this can be shortened to local({x <- 1; x + 1}). See ?local.
One equivalent is a lambda function, whereby, you use the
implicit local({ }) within the function body
(this is a slightly improved answer of #ArtemSokolov's answer).
(function() {
x <- 1
x + 1
})()
This is equivalent to
local({
x <- 1
x + 1
})
Related
I am fairly new to programming in R and I am wondering why this does not work:
w <- c(1,0)
deriv(~x^2+y,c("x","y"),function.arg = TRUE)(w)
I really want to apply the function produced by deriv() on a variable w.
Maybe some background on how to deal with these kinds of "macros" might be helpful...
We can use do.call and pass the 'w' as a list of arguments
do.call(deriv(~x^2+y,c("x","y"),function.arg = TRUE), as.list(w))
Your function exposes two non-default parameters but you only pass one argument. Below would work, if this is your intention:
w <- c(1,0)
deriv( ~ x^2 + y, c("x","y"), function.arg = TRUE)(w, w)
# [1] 2 0
# attr(,"gradient")
# x y
# [1,] 2 1
# [2,] 0 1
Alternatively, set up a default parameter:
w <- c(1,0)
deriv( ~ x^2 + y, c("x","y"), function.arg = function(x, y=2){})(x=w)
# [1] 3 2
# attr(,"gradient")
# x y
# [1,] 2 1
# [2,] 0 1
# MORE READABLE VERSION WITH identity()
myfunc <- deriv( ~x^2 + y, c("x","y"), func = function(x, y=2) identity(x,y))
myfunc(x=w)
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 want to use env_get to evaluate a variable in the grandparent environment (I think) of the mutate call, but I couldn't manage. I'm describing a minimal example below.
Given a list like the following:
library(dplyr)
l <- list(X = 10,
df = tibble(n = seq(-10,10), y = rnorm(21), z = runif(21)))
And custom mutate for these lists.
mutate_.list <- function(.data, ...){
mutate_(.data$df, ...)
}
I want a function that can be run inside the mutate and can use the value of
X. Something like the following which doesn't work:
addX <- function(x) {
X <- rlang::env_get(env = parent.frame(2), 'X', inherit = TRUE)
x + X
}
This works as expected.
mutate(l, n + 1)
And I would like to be able to do this:
mutate(l, addX(n))
And this doesn't work. I guess I should go up parents somehow and be able to
refer to the list, but I couldn't manage. I tried to get the plausible names of the list arguments like this:
addX_test <- function(x) {
print(rlang::env_names(parent.frame(1)))
x
}
mutate(l, addX_test(n))
But I get stuff like the following:
[1] "~" ".top_env"
[3] ".__tidyeval_data_mask__." ".env"
Any pointers? Is it even doable?
Your X is a field inside l, so it's not directly visible in the corresponding environment. If you search for l instead, you can then access its fields.
addX( 1:3 ) # Error: object 'X' not found
addX_v2 <- function(x) {
ll <- rlang::env_get(env = parent.frame(2), 'l', inherit = TRUE)
x + ll$X
}
addX_v2( 1:3 )
# [1] 11 12 13
mutate( l, addX_v2(n) )
# # A tibble: 21 x 4
# n y z `addX_v2(n)`
# <int> <dbl> <dbl> <dbl>
# 1 -10 0.693 0.359 0
# 2 -9 -1.43 0.378 1
# 3 -8 -0.287 0.289 2
# 4 -7 -1.27 0.149 3
# ...
In general, it's not advisable to traverse the calling stack like that, because it breaks modularity of your code and introduces non-trivial dependencies that could lead to obscure bugs. In my opinion, a better approach is to use a function generator (function that returns a function), which will effectively bind the value of X to the computation that uses it:
Xadder <- function( .list ) { function(x) {x + .list$X} }
addX_v3 <- Xadder( l )
addX_v3(1:3)
# [1] 11 12 13
mutate( l, addX_v3(n) ) # Works as expected
Note that this version is more robust to a name change for your list, because it no longer searches for l directly.
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
Does R have a concept of += (plus equals) or ++ (plus plus) as c++/c#/others do?
No, it doesn't, see: R Language Definition: Operators
Following #GregaKešpret you can make an infix operator:
`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x
R doesn't have a concept of increment operator (as for example ++ in C). However, it is not difficult to implement one yourself, for example:
inc <- function(x)
{
eval.parent(substitute(x <- x + 1))
}
In that case you would call
x <- 10
inc(x)
However, it introduces function call overhead, so it's slower than typing x <- x + 1 yourself. If I'm not mistaken increment operator was introduced to make job for compiler easier, as it could convert the code to those machine language instructions directly.
R doesn't have these operations because (most) objects in R are immutable. They do not change. Typically, when it looks like you're modifying an object, you're actually modifying a copy.
Increment and decrement by 10.
require(Hmisc)
inc(x) <- 10
dec(x) <- 10
We released a package, roperators, to help with this kind of thing. You can read more about it here: https://happylittlescripts.blogspot.com/2018/09/make-your-r-code-nicer-with-roperators.html
install.packages('roperators')
require(roperators)
x <- 1:3
x %+=% 1; x
x %-=% 3; x
y <- c('a', 'b', 'c')
y %+=% 'text'; y
y %-=% 'text'; y
# etc
We can override +. If unary + is used and its argument is itself an unary + call, then increment the relevant object in the calling environment.
`+` <- function(e1,e2){
# if binary `+`, keep original behavior
if(!missing(e2)) return(base::`+`(e1, e2))
# if inner call isn't unary `+` called on language object,
# keep original behavior
inner_call <- substitute(e1)
inner_call_is_plus_on_lng <-
length(inner_call) == 2 &&
identical(inner_call[[1]], quote(`+`)) &&
is.language(inner_call[[2]])
if(!inner_call_is_plus_on_lng) return(base::`+`(e1))
eval.parent(substitute(X <- X + 1, list(X = inner_call[[2]])))
}
x <- 10
++x
x
#> [1] 11
other operations don't change :
x + 2
#> [1] 13
x ++ 2
#> [1] 13
+x
#> [1] 11
x
#> [1] 11
I can't really recommend it since you're messing with primitives which are optimised for a reason.
We can also use inplace
library(inplace)
x <- 1
x %+<-% 2
If you want to use i++ in an array to increment the index, you can try i <- i + 1, for example,
k = 0
a = 1:4
for (i in 1:4)
cat(a[k <- k + 1], " ")
# 1 2 3 4
but here <- can NOT be replaced with =, which does not update the index,
k = 0
a = 1:4
for (i in 1:4)
cat(a[k = k + 1], " ")
# 1 1 1 1
since = and <- are not always equivalent, as said in ?`<-`