diff --git a/DESCRIPTION b/DESCRIPTION index a3ce6ba..fd05b28 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,5 +9,7 @@ URL: https://github.com/hadley/memoise BugReports: https://github.com/hadley/memoise/issues Imports: digest -Suggests: testthat +Suggests: + testthat License: MIT + file LICENSE +RoxygenNote: 5.0.0 diff --git a/NAMESPACE b/NAMESPACE index f172c4a..c365658 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ -# Generated by roxygen2 (4.1.1): do not edit by hand +# Generated by roxygen2: do not edit by hand +S3method(print,memoised) export(forget) export(is.memoised) export(is.memoized) diff --git a/NEWS.md b/NEWS.md index 1f2f039..96b7ccd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # Version 0.2.99.9000 +* Memoised functions now have a print method which displays the original + function definition, rather than the memoisation code (#15, @jimhester). * A memoised function now has the same interface as the original function, if the original function is known when `memoise` is called. (Otherwise, the old behavior is invoked, with a warning.) (#14, @krlmlr) diff --git a/R/memoise.r b/R/memoise.r index 0ce2ad1..8a0697d 100644 --- a/R/memoise.r +++ b/R/memoise.r @@ -141,6 +141,8 @@ memoise_new <- function(f, envir) { memo_f_env$digest <- digest environment(memo_f) <- memo_f_env + class(memo_f) <- c("memoised", "function") + memo_f } @@ -168,10 +170,16 @@ memoise_old <- function(f) { invisible(res$value) } } - attr(memo_f, "memoised") <- TRUE + class(memo_f) <- c("memoised", "function") memo_f } +#' @export +print.memoised <- function(x, ...) { + cat("Memoised Function:\n") + print(environment(x)$f) +} + #' Forget past results. #' Resets the cache of a memoised function. #' @@ -211,5 +219,5 @@ forget <- function(f) { #' is.memoised(lm) # FALSE #' is.memoised(mem_lm) # TRUE is.memoised <- is.memoized <- function(f) { - is.function(f) && identical(attr(f, "memoised"), TRUE) + is.function(f) && inherits(f, "memoised") } diff --git a/man/forget.Rd b/man/forget.Rd index 986e692..633e40a 100644 --- a/man/forget.Rd +++ b/man/forget.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand +% Generated by roxygen2: do not edit by hand % Please edit documentation in R/memoise.r \name{forget} \alias{forget} diff --git a/man/is.memoised.Rd b/man/is.memoised.Rd index beffc42..dd5e681 100644 --- a/man/is.memoised.Rd +++ b/man/is.memoised.Rd @@ -1,10 +1,10 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand +% Generated by roxygen2: do not edit by hand % Please edit documentation in R/memoise.r \name{is.memoised} \alias{is.memoised} \alias{is.memoized} \title{Test whether a function is a memoised copy. -Memoised copies of functions carry an attribute +Memoised copies of functions carry an attribute \code{memoised = TRUE}, which is.memoised() tests for.} \usage{ is.memoised(f) @@ -14,7 +14,7 @@ is.memoised(f) } \description{ Test whether a function is a memoised copy. -Memoised copies of functions carry an attribute +Memoised copies of functions carry an attribute \code{memoised = TRUE}, which is.memoised() tests for. } \examples{ diff --git a/man/memoise.Rd b/man/memoise.Rd index cf3d072..8ad896c 100644 --- a/man/memoise.Rd +++ b/man/memoise.Rd @@ -1,4 +1,4 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand +% Generated by roxygen2: do not edit by hand % Please edit documentation in R/memoise.r \name{memoise} \alias{memoise} @@ -21,8 +21,8 @@ circumstances, this can provide a very nice speedup indeed. } \details{ There are two main ways to use the \code{memoise} function. Say that -you wish to memoise \code{glm}, which is in the \code{stats} -package; then you could use \cr +you wish to memoise \code{glm}, which is in the \code{stats} +package; then you could use \cr \code{ mem_glm <- memoise(glm)}, or you could use\cr \code{ glm <- memoise(stats::glm)}. \cr The first form has the advantage that you still have easy access to @@ -38,7 +38,7 @@ Two example situations where \code{memoise} could be of use: \item You're debugging or developing something, which involves a lot of re-running the code. If there are a few expensive calls in there, memoising them can make life a lot more pleasant. - If the code is in a script file that you're \code{source()}ing, + If the code is in a script file that you're \code{source()}ing, take care that you don't just put \cr \code{ glm <- memoise(stats::glm)} \cr at the top of your file: that would reinitialise the memoised @@ -49,7 +49,7 @@ Two example situations where \code{memoise} could be of use: } } \examples{ -# a() is evaluated anew each time. memA() is only re-evaluated +# a() is evaluated anew each time. memA() is only re-evaluated # when you call it with a new set of parameters. a <- function(n) { runif(n) } memA <- memoise(a) @@ -60,7 +60,7 @@ replicate(5, memA(2)) # changed-value correctly produces two different outcomes... N <- 4; memA(N) N <- 5; memA(N) -# ... and same-value-but-different-name correctly produces +# ... and same-value-but-different-name correctly produces # the same cached outcome. N <- 4; memA(N) N2 <- 4; memA(N2) @@ -79,24 +79,24 @@ formals(memB) # that the outcome is the same. memB(2, dummy="b") -# You can create multiple memoisations of the same function, -# and they'll be independent. +# You can create multiple memoisations of the same function, +# and they'll be independent. memA(2) memA2 <- memoise(a) memA(2) # Still the same outcome memA2(2) # Different cache, different outcome -# Don't do the same memoisation assignment twice: a brand-new -# memoised function also means a brand-new cache, and *that* +# Don't do the same memoisation assignment twice: a brand-new +# memoised function also means a brand-new cache, and *that* # you could as easily and more legibly achieve using forget(). -# (If you're not sure whether you already memoised something, +# (If you're not sure whether you already memoised something, # use is.memoised() to check.) memA(2) memA <- memoise(a) memA(2) } \seealso{ -\code{\link{forget}}, \code{\link{is.memoised}}, +\code{\link{forget}}, \code{\link{is.memoised}}, \url{http://en.wikipedia.org/wiki/Memoization} } diff --git a/tests/testthat/test-memoise.R b/tests/testthat/test-memoise.R index 912bdd5..786846e 100644 --- a/tests/testthat/test-memoise.R +++ b/tests/testthat/test-memoise.R @@ -165,3 +165,19 @@ test_that("can memoise primitive", { expect_equal(fm(2, 3), 2 + 3) expect_equal(fm(1, 2), 1 + 2) }) + +test_that("printing a memoised function prints the original definition", { + + fn <- function(j) { i <<- i + 1; i } + + fnm <- memoise(fn) + + fn_output <- capture.output(fn) + str(fn_output) + fnm_output <- capture.output(fnm) + str(fnm_output) + + expect_equal(fnm_output[1], "Memoised Function:") + + expect_equal(fnm_output[-1], fn_output) +})