13

Running

TRUE |> `!`() 

Results in:

Error in !NULL : function '!' not supported in RHS call of a pipe (<input>:1:9) 

When using magrittr, there is a not() alias, but this does not work for base R. See: Negation `!` in a dplyr pipeline `%>%`

2
  • 1
    Perhaps it's a one-off buglet, but R doesn't like that symbol on the RHS of the |> pipe, I don't see a reason why. You can do fun <- `!`; TRUE |> fun().
    – r2evans
    Commented2 days ago
  • 3
    while this is a theoretically interesting question, I am mildly skeptical how useful it is in practice; in the absence of context, it feels like a case of over-piping.Commented2 days ago

5 Answers 5

14

Simply adding brackets:

TRUE |> (`!`)() #[1] FALSE 
2
  • 1
    Or using {. eg TRUE |> {`!`}()
    – Onyambu
    Commentedyesterday
  • 2
    This is nice and simple but might be worth adding that this is not parsed as !TRUE. You get an extra function call - the parentheses function - as this is interpreted as `(`(`!`)(TRUE). R is weird.
    – SamR
    Commentedyesterday
8

Negate()

One base R approach is to Negate() the identity() function:

TRUE |> Negate(identity)() # [1] FALSE 

This is parsed as Negate(identity)(TRUE), i.e. !TRUE.

isFALSE()

Alternatively, you can use isFALSE(), though this is limited to vectors of length one:

TRUE |> isFALSE() # [1] FALSE 

If you have a longer logical vector, v, you can *apply() this function. It's important to be aware that this is stricter than Negate(), both in terms of how it handles NA and how it treats other truthy/falsy values:

# NA values v <- c(TRUE, NA, FALSE) v |> Negate(identity)() # [1] FALSE NA TRUE v |> sapply(isFALSE) # [1] FALSE FALSE TRUE # Other falsy values e.g. 0 handled differently 0 |> Negate(identity)() # [1] TRUE 0 |> isFALSE() # [1] FALSE 

This is explicit, but whether its treatment of NA is desired will depend on your goal.

xor()

Finally, if you want to be perhaps a little too clever about it, you can use xor(), taking advantage of the fact that xor(x, TRUE) is equivalent to !x, because:

xyxor(x, y)
FALSETRUETRUE
TRUETRUEFALSE
v <- c(TRUE, NA, FALSE) v |> xor(TRUE) # [1] FALSE NA TRUE identical(v |> xor(TRUE), !v) # [1] TRUE 
    6

    Why not define not() yourself?

    not <- function(x) !x TRUE |> not() 
    1
    • 3
      I would probably do this too as it's the clearest but I assumed they didn't want to as it's pretty similar to an answer in the question they linked
      – SamR
      Commented2 days ago
    6

    It's

    > TRUE |> base::`!`() [1] FALSE 
    1
    • 2
      Also nice and straightforward but maybe also worth noting that as (almost) everything in R is a function, you get an extra function call here to ::. R does not parse this as !TRUE but as `::`(base, `!`)(TRUE).
      – SamR
      Commentedyesterday
    3

    With the native base R pipe operator you can do

    TRUE |> { \(.) !. }() # [1] FALSE 

    If this is useful depends on the task.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.