Can (a==1 & a==2 & a==3) ever evaluate to TRUE?

4 minute read

A blogpost inspired by a Stackoverflow question: “Can (a==1 && a==2 && a==3) ever evaluate to true?”

Yesterday I run into this topic on SO, about a JavaScript question a user had during a job interview.

The question is quite straightforward:

Is it ever possible that (a==1 && a==2 && a==3) could evaluate to true, in JavaScript?

As a little challenge, I asked myself the same question, but with R (and with a little transformation): can a==1 & a==2 & a==3 ever evaluate to TRUE? Once I’ve found how to, I challenged Twitter, and was glad to read some creative answers.

One amazing thing with R is that you can achieve the same result by taking several roads. So, here are a compilation of the answers I received.

First question

Overriding base functions

x <- 1
`&` <- function(x,y) {T}
x == 1 & x == 2 & x == 3
## [1] TRUE
`&` <- function(x,y) {T}
x == 1 & x == 2 & x == 3
## [1] TRUE

Number 2

Overriding base functions

x = 1; `&` <- `>`
x == 1 & x == 2 & x == 3
## [1] TRUE
x == 3 & x == 2 & x == 1
## [1] FALSE
x <-1
`&` <- function(e1,e2) e1
x == 1 & x == 2 & x == 3
## [1] TRUE
x == 3 & x == 2 & x == 1
## [1] FALSE

Question 3

A really nice way to frame it

make_x <- function(){
  counter <- 1
  inc <- function() counter <<- counter + 1
  value <- function() counter
  structure(list(inc = inc, value = value), class = "x")
}
print.x <- function(x){
  v <-x$value()
  x$inc()
  print(v)
  v
}
x <- make_x()
x
## [1] 1
x 
## [1] 2
x
## [1] 3
rm(list=ls())
library(R6)
make_x <- R6Class("x", 
                  public = list(x = 1,
                                print = function(){
                                  print(self$x)
                                  self$x <- self$x + 1
                                }
                  )
)
x <- make_x$new()
x
## [1] 1
x
## [1] 2
x
## [1] 3
x <- structure(0L, class = "x")
print.x <- function(x) print(as.integer(x <<- x + 1L ))
x
## [1] 1
x
## [1] 2
x
## [1] 3

Sadly, these three solutions don’t answer the three questions in one shot.

One answer to rule them all

One answer that can do the three at once, by Alek Vladimir Nevski.

x <- c(1,1)
`==` <- function(foo,bar){foo[1]+bar}
`&` <- function(foo,bar){
  if(isTRUE(foo) || identical(foo,FALSE)){
  foo+2<bar
  }else{
      foo < bar
    }
  }

class(x) <- c("myclass",class(x)) 
print.myclass = function(x){
  t <- x[2];
  x[2] <<- x[2]+1;print(t)
  }
# First quizz :
x == 1 & x == 2 & x == 3
## [1] TRUE
# Second quizz : 
x == 1 & x == 2 & x == 3
## [1] TRUE
x == 3 & x == 2 & x == 1
## [1] FALSE
# Third quizz :
x
## [1] 1
x
## [1] 2
x
## [1] 3

With active binding

What I had in mind from the beginning was to use active binding. I’ll let you dig into this blogpost if ever you want to know more about it, but basically we bind a function to a symbol instead of a value (which is static binding).

It is called active because each time you evaluate this symbol, R executes a function, instead of looking for a value.

So, here’s my way to answer the “Can (a==1 && a==2 && a==3) ever evaluate to true?”:

rm(list=ls())
makeActiveBinding(sym = "x", env = .GlobalEnv,
                  fun = function(value){
                    if (missing(value)) {
                      if (i == 3){
                        i <<- 1
                      } else {
                        i <<- i + 1
                      }
                      return(i)
                    } 
                  }
)
i <- 0
# First quizz :
x == 1 & x == 2 & x == 3
## [1] TRUE
# Second quizz : 
x == 1 & x == 2 & x == 3
## [1] TRUE
x == 3 & x == 2 & x == 1
## [1] FALSE
# Third quizz :
x
## [1] 1
x
## [1] 2
x
## [1] 3

Here, the difference is that the values are actually equal: we’re not changing the way == or & behave - it’s the value of x that is changing each time we’re calling it. With active binding, R is executing the function defined in fun, a function that takes i, restarts the counter or incremente it of 1, and returns it.

How is this interesting?

Beside being a nice R brain game, this example is a nice occasion to introduce about the concept of binding, and remind that we are most of the time assuming is static: most of the answers (in fact, all except one) assume that the value of x is static, and that we should tweak the other operators :)

Read more about binding:

Categories:

Updated:

Leave a Comment