Search code examples
rread-eval-print-loop

Applying a function to the last result in R with minimal typing


On Twitter I asked the following:

In RStudio, is there an easy way to pipe the last result stored in .Last.value into a function. Say I did:

tbl <- CreateTable(x).

I now want to do View(tbl) but with less typing. Just type

.View

or something. Is that possible? #rstats #rstudio

Is there maybe a general way to do this?


Solution

  • Here are a few ways, this is all strange stuff so I hope you'll keep it for interactive use, won't put anything in your RProfile and won't share code using those :).

    1 - create a binding for .

    . will be a shortcut for .Last.Value, saving most of the typing. magrittr pipes and functional sequences will still work, and so will purrr lambdas.

    makeActiveBinding(".", function() .Last.value, .GlobalEnv)
    4
    sqrt(.) # 2
    

    If you have a µ, a λ or another compliant special character easily accessible on your keyboard it might be a good idea to use it instead.

    2 - hacking print.function

    We can hack print.function so it runs the function on the last value.

    Here I couldn't use .Last.value because it's the value of the function itself, so I need to re-execute the previous call, so in some cases it might be slow.

    print.function <- function(x){
      tf <- tempfile()
      savehistory(tf)
      last_calls <- parse(text=tail(readLines(tf),2))
      if(as.list(last_calls[[2]])[[1]] == quote(print))
        base:::print.function(x) else print(x(eval.parent(last_calls[[1]])))
    }
    4
    sqrt # 2
    4
    print(sqrt) # the actual definition
    

    3 - Use package doubt

    We can build a dubious operator that will use .Last.value :

    # remotes::install_github("moodymudskipper/doubt")
    library(doubt)
    `?+{fun}` <- function(fun){ fun(.Last.value)}
    4
    ?+sqrt # 2
    

    4 - give a class to the functions you care about

    And define a method for an unary operator (+, -, and ! will all work) :

    class(sqrt) <- class(summary) <- class(View) <- "magic_function"
    `+.magic_function` <- function(fun){ fun(.Last.value)}
    4
    +sqrt # 2