RにおけるLazy Evaluation

Loggerの引数にRの式そのまま書けるようにしたいなあと思った。そういうのって他にどういう関数があったかなあと思ったらsystem.timeがまさにそんな感じ。関数の定義を読む。

system.time <- function(expr, gcFirst = TRUE)
{
    ppt <- function(y) {
        if(!is.na(y[4])) y[1] <- y[1] + y[4]
        if(!is.na(y[5])) y[2] <- y[2] + y[5]
        y[1:3]
    }
    if(!exists("proc.time")) return(rep(NA_real_, 5))
    if(gcFirst)  gc(FALSE)
    time <- proc.time()
    ## need on.exit after 'time' has been set:
    ## on some systems proc.time throws an error.
    on.exit(cat("Timing stopped at:", ppt(proc.time() - time), "\n"))
    expr # evaluated here because of lazy evaluation
    new.time <- proc.time()
    on.exit()
    structure(new.time - time, class="proc_time")
}

コメントしてあるところに「# evaluated here because of lazy evaluation」とある。つまり、exprで式だけ持っておいて、そこまでその式を評価しない。つまり遅延評価をすることで、色々できそうである、ということが判明。そういえばRの基本となるオブジェクトにexpressionというのがあったなあと思い出すなどした。そういうわけでこういうことができることが分かった。

> (function(exp){exp})(print("hoge"))
[1] "hoge"

ほえー。

Further Reading

  • R Language Definition
    • p2のオブジェクトの種類についての説明
      • 「expression 表現式オブジェクト」
    • p4の表現式オブジェクトのところ
      • 言語オブジェクトとの違いについて
    • p32の表現式オブジェクトの評価のところ