Home > Software design >  Fill in parts of code previously saved in an object
Fill in parts of code previously saved in an object

Time:12-13

I have a code in which I want to be able to specify a certain condition, and then fill-in this condition at a later point in my code, executing it as regular code. A simple example shows it. The following code returns a certain value for d depending on the values sampled for a and b.

a <- as.numeric(sample(1:2,1))
b <- as.numeric(sample(1:2,1))
d <- ifelse(a==1 & b==1,3,0)

But let's say I want to make it more flexible, and allow any condition to be specified, and then simply fill it in within the ifelse. So for example we could have:

a <- as.numeric(sample(1:2,1))
b <- as.numeric(sample(1:2,1))
c <- as.numeric(sample(1:2,1))

And I would like to specify two conditions:

condition_1 <- "a==1"
condition_2 <- "b==1"

or

condition_1 <- "a==1"
condition_2 <- "c==1"

and so on. Then I would like to fill in this conditions into ifelse. This does not work:

d <- ifelse(noquote(condition_1) & noquote(condition_1),3,0)

This also does not work:

d <- ifelse(paste(noquote(condition_1)) & paste(noquote(condition_1)),3,0)

I have tried anything I could think of but with no success. Is there a way to do this? More in general, how can I store parts of code, and then past them into the code at a later point and have it executed like the rest of the code? Please do not provide workarounds that only work for this specific example. I need to do something analogous in a much more complex code.

CodePudding user response:

"Storing parts of code [for later use]" sounds to me like using functions. You can pass functions as arguments to other functions. So you could do something like:

dFunc1 <- function(aVal, bVal) {
  ifelse(a == aVal &  b == bVal, 3, 0)
}
set.seed(1234)
a <- as.numeric(sample(1:2,1))
b <- as.numeric(sample(1:2,1))
d <- dFunc1(1, 1)
a
b
d
> a
[1] 2
> b
[1] 2
> d
[1] 0

and then

set.seed(1234)
dFunc2 <- function(aVal, cVal) {
  ifelse(a == aVal &  c == cVal, 3, 0)
}
c <- as.numeric(sample(1:2,1))
d <- dFunc2(1, 1)
c
d
> c
[1] 2
> d
[1] 0

If your derivations are embedded in another function, that's not a problem.

doItAll <- function(f, ...) {
  set.seed(1234)
  a <- as.numeric(sample(1:2,1))
  b <- as.numeric(sample(1:2,1))
  c <- as.numeric(sample(1:2,1))
  d <- f(...)
  return(list("a"=a, "b"=b, "c"=c, "d"=d))
}

doItAll(dFunc1, aVal=1, bVal=1)
$a
[1] 2

$b
[1] 2

$c
[1] 2

$d
[1] 0

and

doItAll(dFunc2, aVal=1, cVal=1)
$a
[1] 2

$b
[1] 2

$c
[1] 2

$d
[1] 0

The use of the elipsis (...) is key to the ability of passing arbitrary arguments to functions that are called from inside another function.

CodePudding user response:

In the end I decided to solve this with a set of if and else if conditions. It seemed more practical than setting up a function as suggested by Limey.

  • Related