From e9619d3f72638a5912d06823dabaa2e96fbb0cc2 Mon Sep 17 00:00:00 2001 From: Aleksander Chlebowski <114988527+chlebowa@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:20:38 +0100 Subject: [PATCH] 150 collate documentation (#166) Closes #150 Collated documentation for `qenv`, `eval_code`, `within`, and `get_code` into one page (composed of multiple files). Cleaned up usage sections of all help pages. Some stylistic updates. --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- NAMESPACE | 8 --- R/qenv-concat.R | 24 +++++---- R/qenv-constructor.R | 20 +++++--- R/qenv-eval_code.R | 39 +++++++------- R/qenv-get_code.R | 34 +++++++------ R/qenv-get_var.R | 35 ++++++------- R/qenv-get_warnings.R | 28 ++++++----- R/qenv-join.R | 30 ++++++----- R/qenv-show.R | 14 ++++-- R/qenv-within.R | 38 +++++++------- man/concat.Rd | 11 ++-- man/eval_code.Rd | 40 --------------- man/get_code.Rd | 35 ------------- man/get_var.Rd | 27 +++------- man/get_warnings.Rd | 15 ++---- man/join.Rd | 17 +++---- man/qenv.Rd | 109 +++++++++++++++++++++++++++++++++++++--- man/show-qenv-method.Rd | 8 +-- man/within.Rd | 70 -------------------------- 19 files changed, 268 insertions(+), 334 deletions(-) delete mode 100644 man/eval_code.Rd delete mode 100644 man/get_code.Rd delete mode 100644 man/within.Rd diff --git a/NAMESPACE b/NAMESPACE index c50d5da9..3d52ad4c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,14 +12,6 @@ export(join) export(new_qenv) export(qenv) exportClasses(qenv) -exportMethods("[[") -exportMethods(concat) -exportMethods(eval_code) -exportMethods(get_code) -exportMethods(get_var) -exportMethods(get_warnings) -exportMethods(join) -exportMethods(new_qenv) exportMethods(show) import(grDevices) importFrom(lifecycle,badge) diff --git a/R/qenv-concat.R b/R/qenv-concat.R index 60d9a1ef..9af3ef57 100644 --- a/R/qenv-concat.R +++ b/R/qenv-concat.R @@ -1,13 +1,16 @@ -#' Concatenate two `qenv` objects +#' Concatenate Two `qenv` Objects #' #' Combine two `qenv` objects by simple concatenate their environments and the code. +#' #' We recommend to use the `join` method to have a stricter control #' in case `x` and `y` contain duplicated bindings and code. #' RHS argument content has priority over the LHS one. +#' #' @param x (`qenv`) #' @param y (`qenv`) -#' @include qenv-errors.R +#' #' @return `qenv` object. +#' #' @examples #' q <- qenv() #' q1 <- eval_code(q, expression(iris1 <- iris, mtcars1 <- mtcars)) @@ -16,11 +19,18 @@ #' q2 <- eval_code(q2, "mtcars2 <- mtcars") #' qq <- concat(q1, q2) #' get_code(qq) +#' +#' @include qenv-errors.R +#' +#' @name concat +#' @rdname concat +#' @aliases concat,qenv,qenv-method +#' @aliases concat,qenv.error,ANY-method +#' @aliases concat,qenv,qenv.error-method +#' #' @export setGeneric("concat", function(x, y) standardGeneric("concat")) -#' @rdname concat -#' @export setMethod("concat", signature = c("qenv", "qenv"), function(x, y) { y@id <- c(x@id, y@id) y@code <- c(x@code, y@code) @@ -33,14 +43,10 @@ setMethod("concat", signature = c("qenv", "qenv"), function(x, y) { y }) -#' @rdname concat -#' @export -setMethod("concat", signature = c("qenv.error"), function(x, y) { +setMethod("concat", signature = c("qenv.error", "ANY"), function(x, y) { x }) -#' @rdname concat -#' @export setMethod("concat", signature = c("qenv", "qenv.error"), function(x, y) { y }) diff --git a/R/qenv-constructor.R b/R/qenv-constructor.R index 13d05923..66af8846 100644 --- a/R/qenv-constructor.R +++ b/R/qenv-constructor.R @@ -1,11 +1,16 @@ -#' Initialize `qenv` object +#' Code Tracking With `qenv` Object #' -#' Create an empty `qenv` object. +#' @description +#' `r badge("stable")` +#' +#' Create a `qenv` object and evaluate code in it to track code history. +#' +#' @details #' #' `qenv()` instantiates a `qenv` with an empty environment. #' Any changes must be made by evaluating code in it with `eval_code` or `within`, thereby ensuring reproducibility. #' -#' `new_qenv()` (deprecated and not recommended) +#' `new_qenv()` (`r badge("deprecated")` and not recommended) #' can instantiate a `qenv` object with data in the environment and code registered. #' #' @name qenv @@ -14,7 +19,7 @@ #' # create empty qenv #' qenv() #' -#' @return `qenv` object. +#' @return `qenv` and `new_qenv` return a `qenv` object. #' #' @export qenv <- function() { @@ -41,13 +46,15 @@ qenv <- function() { #' @aliases new_qenv,environment,language-method #' @aliases new_qenv,environment,missing-method #' @aliases new_qenv,missing,missing-method +#' +#' @seealso [`get_var()`], [`get_warnings()`], [`join()`], [`concat()`] +#' #' @export setGeneric("new_qenv", function(env = new.env(parent = parent.env(.GlobalEnv)), code = character()) { lifecycle::deprecate_warn(when = " 0.4.2", what = "new_qenv()", with = "qenv()", always = TRUE) standardGeneric("new_qenv") }) -#' @export setMethod( "new_qenv", signature = c(env = "environment", code = "expression"), @@ -56,7 +63,6 @@ setMethod( } ) -#' @export setMethod( "new_qenv", signature = c(env = "environment", code = "character"), @@ -72,7 +78,6 @@ setMethod( } ) -#' @export setMethod( "new_qenv", signature = c(env = "environment", code = "language"), @@ -81,7 +86,6 @@ setMethod( } ) -#' @export setMethod( "new_qenv", signature = c(code = "missing", env = "missing"), diff --git a/R/qenv-eval_code.R b/R/qenv-eval_code.R index e86af332..3d7f2fe3 100644 --- a/R/qenv-eval_code.R +++ b/R/qenv-eval_code.R @@ -1,27 +1,32 @@ -#' Evaluate the code in the `qenv` environment +#' Evaluate Code in `qenv` #' -#' Given code is evaluated in the `qenv` environment and appended to the `code` slot. This means -#' that state of the environment is always a result of the stored code (if `qenv` was initialized) -#' with reproducible code. -#' -#' @name eval_code +#' @details +#' `eval_code` evaluates given code in the `qenv` environment and appends it to the `code` slot. +#' Thus, if the `qenv` had been instantiated empty, contents of the environment are always a result of the stored code. #' #' @param object (`qenv`) -#' @param code (`character` or `language`) code to evaluate. Also accepts and stores comments +#' @param code (`character` or `language`) code to evaluate. If `character`, comments are retained. +#' +#' @return +#' `eval_code` returns a `qenv` object with `expr` evaluated or `qenv.error` if evaluation fails. #' #' @examples +#' # evaluate code in qenv #' q <- qenv() -#' q1 <- eval_code(q, quote(a <- 1)) -#' q2 <- eval_code(q1, quote(library(checkmate))) -#' q3 <- eval_code(q2, quote(assert_number(a))) +#' q <- eval_code(q, "a <- 1") +#' q <- eval_code(q, quote(library(checkmate))) +#' q <- eval_code(q, expression(assert_number(a))) #' -#' @return `qenv` object. +#' @name eval_code +#' @rdname qenv +#' @aliases eval_code,qenv,character-method +#' @aliases eval_code,qenv,language-method +#' @aliases eval_code,qenv,expression-method +#' @aliases eval_code,qenv.error,ANY-method #' #' @export setGeneric("eval_code", function(object, code) standardGeneric("eval_code")) -#' @rdname eval_code -#' @export setMethod("eval_code", signature = c("qenv", "character"), function(object, code) { id <- sample.int(.Machine$integer.max, size = 1) @@ -83,21 +88,15 @@ setMethod("eval_code", signature = c("qenv", "character"), function(object, code object }) -#' @rdname eval_code -#' @export setMethod("eval_code", signature = c("qenv", "language"), function(object, code) { eval_code(object, code = format_expression(code)) }) -#' @rdname eval_code -#' @export setMethod("eval_code", signature = c("qenv", "expression"), function(object, code) { eval_code(object, code = format_expression(code)) }) -#' @rdname eval_code -#' @export -setMethod("eval_code", signature = "qenv.error", function(object, code) { +setMethod("eval_code", signature = c("qenv.error", "ANY"), function(object, code) { object }) diff --git a/R/qenv-get_code.R b/R/qenv-get_code.R index c377cd56..ff6808f0 100644 --- a/R/qenv-get_code.R +++ b/R/qenv-get_code.R @@ -1,17 +1,25 @@ -#' Get code from `qenv` +#' Get Code From `qenv` +#' +#' @details +#' `get_code` retrieves the code stored in the `qenv`. `...` passes arguments to methods. #' -#' @name get_code #' @param object (`qenv`) -#' @param deparse (`logical(1)`) if the returned code should be converted to character. -#' @param ... arguments passed to methods. -#' @return named `character` with the reproducible code. +#' @param deparse (`logical(1)`) flag specifying whether to return code as `character` or `expression`. +#' @param ... see `Details` +#' +#' @return +#' `get_code` returns the traced code (from `@code` slot) in the form specified by `deparse`. +#' #' @examples -#' q <- qenv() -#' q1 <- eval_code(q, code = quote(a <- 1)) -#' q2 <- eval_code(q1, code = quote(b <- a)) -#' q3 <- eval_code(q2, code = quote(d <- 2)) -#' get_code(q3) -#' get_code(q3, deparse = FALSE) +#' # retrieve code +#' get_code(q) +#' get_code(q, deparse = FALSE) +#' +#' @name get_code +#' @rdname qenv +#' @aliases get_code,qenv-method +#' @aliases get_code,qenv.error-method +#' #' @export setGeneric("get_code", function(object, deparse = TRUE, ...) { # this line forces evaluation of object before passing to the generic @@ -23,8 +31,6 @@ setGeneric("get_code", function(object, deparse = TRUE, ...) { standardGeneric("get_code") }) -#' @rdname get_code -#' @export setMethod("get_code", signature = "qenv", function(object, deparse = TRUE) { checkmate::assert_flag(deparse) if (deparse) { @@ -34,8 +40,6 @@ setMethod("get_code", signature = "qenv", function(object, deparse = TRUE) { } }) -#' @rdname get_code -#' @export setMethod("get_code", signature = "qenv.error", function(object, ...) { stop( errorCondition( diff --git a/R/qenv-get_var.R b/R/qenv-get_var.R index dd961b0a..c776b1ec 100644 --- a/R/qenv-get_var.R +++ b/R/qenv-get_var.R @@ -1,10 +1,12 @@ -#' Get object from the `qenv` environment +#' Get Object From `qenv` +#' +#' Retrieve variables from the `qenv` environment. +#' +#' @param object,x (`qenv`) +#' @param var,i (`character(1)`) variable name. #' -#' Get object from the `qenv` environment. -#' @param object (`qenv`) -#' @param var (`character(1)`) name of the variable to pull from the environment. -#' @name get_var #' @return The value of required variable (`var`) within `qenv` object. +#' #' @examples #' q <- qenv() #' q1 <- eval_code(q, code = quote(a <- 1)) @@ -12,6 +14,11 @@ #' get_var(q2, "b") #' q2[["b"]] #' +#' @name get_var +#' @rdname get_var +#' @aliases get_var,qenv,character-method +#' @aliases get_var,qenv.error,ANY-method +#' #' @export setGeneric("get_var", function(object, var) { grDevices::pdf(nullfile()) @@ -19,9 +26,6 @@ setGeneric("get_var", function(object, var) { standardGeneric("get_var") }) - -#' @rdname get_var -#' @export setMethod("get_var", signature = c("qenv", "character"), function(object, var) { tryCatch( get(var, envir = object@env), @@ -32,29 +36,20 @@ setMethod("get_var", signature = c("qenv", "character"), function(object, var) { ) }) -#' @rdname get_var -#' @export -setMethod("get_var", signature = "qenv.error", function(object, var) { +setMethod("get_var", signature = c("qenv.error", "ANY"), function(object, var) { stop(errorCondition( list(message = conditionMessage(object)), class = c("validation", "try-error", "simpleError") )) }) - -#' @param x (`qenv`) -#' @param i (`character`) name of the binding in environment (name of the variable) -#' @param j not used -#' @param ... not used #' @rdname get_var -#' @export -setMethod("[[", signature = c("qenv", "ANY", "missing"), function(x, i, j, ...) { +setMethod("[[", signature = c("qenv", "ANY"), function(x, i) { get_var(x, i) }) -#' @rdname get_var #' @export -`[[.qenv.error` <- function(x, i, j, ...) { +`[[.qenv.error` <- function(x, i) { stop(errorCondition( list(message = conditionMessage(x)), class = c("validation", "try-error", "simpleError") diff --git a/R/qenv-get_warnings.R b/R/qenv-get_warnings.R index 1ba2edce..e6ad0b5e 100644 --- a/R/qenv-get_warnings.R +++ b/R/qenv-get_warnings.R @@ -1,9 +1,10 @@ -#' Get the warnings of `qenv` object +#' Get Warnings From `qenv` Object +#' +#' Retrieve all warnings raised during code evaluation in a `qenv`. #' #' @param object (`qenv`) #' -#' @return `character` containing warning information or `NULL` if no warnings -#' @export +#' @return `character` containing warning information or `NULL` if no warnings. #' #' @examples #' data_q <- qenv() @@ -13,6 +14,13 @@ #' bquote(p <- hist(iris_data[, .("Sepal.Length")], ff = "")) #' ) #' cat(get_warnings(warning_qenv)) +#' +#' @name get_warnings +#' @rdname get_warnings +#' @aliases get_warnings,qenv-method +#' @aliases get_warnings,qenv.error-method +#' @aliases get_warnings,NULL-method +#' #' @export setGeneric("get_warnings", function(object) { # this line forces evaluation of object before passing to the generic @@ -24,14 +32,6 @@ setGeneric("get_warnings", function(object) { standardGeneric("get_warnings") }) -#' @rdname get_warnings -#' @export -setMethod("get_warnings", signature = c("qenv.error"), function(object) { - NULL -}) - -#' @rdname get_warnings -#' @export setMethod("get_warnings", signature = c("qenv"), function(object) { if (all(object@warnings == "")) { return(NULL) @@ -56,8 +56,10 @@ setMethod("get_warnings", signature = c("qenv"), function(object) { ) }) -#' @rdname get_warnings -#' @export +setMethod("get_warnings", signature = c("qenv.error"), function(object) { + NULL +}) + setMethod("get_warnings", "NULL", function(object) { NULL }) diff --git a/R/qenv-join.R b/R/qenv-join.R index a63534dd..56fd2591 100644 --- a/R/qenv-join.R +++ b/R/qenv-join.R @@ -1,6 +1,7 @@ -#' Join two `qenv` objects +#' Join `qenv` Objects +#' +#' Checks and merges two `qenv` objects into one `qenv` object. #' -#' `join()` perform checks and merges two `qenv` objects into one `qenv` object. #' Any common code at the start of the `qenvs` is only placed once at the start of the joined `qenv`. #' This allows consistent behavior when joining `qenvs` which share a common ancestor. #' See below for an example. @@ -105,8 +106,9 @@ #' #' @param x (`qenv`) #' @param y (`qenv`) -#' @include qenv-errors.R +#' #' @return `qenv` object. +#' #' @examples #' q <- qenv() #' q1 <- eval_code(q, expression(iris1 <- iris, mtcars1 <- mtcars)) @@ -123,11 +125,17 @@ #' # get_code only has "x <- 1" occurring once #' get_code(join_q) #' +#' @include qenv-errors.R +#' +#' @name join +#' @rdname join +#' @aliases join,qenv,qenv-method +#' @aliases join,qenv,qenv.error-method +#' @aliases join,qenv.error,ANY-method +#' #' @export setGeneric("join", function(x, y) standardGeneric("join")) -#' @rdname join -#' @export setMethod("join", signature = c("qenv", "qenv"), function(x, y) { join_validation <- .check_joinable(x, y) @@ -148,18 +156,14 @@ setMethod("join", signature = c("qenv", "qenv"), function(x, y) { x }) -#' @rdname join -#' @export -setMethod("join", signature = "qenv.error", function(x, y) { - x -}) - -#' @rdname join -#' @export setMethod("join", signature = c("qenv", "qenv.error"), function(x, y) { y }) +setMethod("join", signature = c("qenv.error", "ANY"), function(x, y) { + x +}) + #' If two `qenv` can be joined #' #' Checks if two `qenv` objects can be combined. diff --git a/R/qenv-show.R b/R/qenv-show.R index db78582d..ab0639e8 100644 --- a/R/qenv-show.R +++ b/R/qenv-show.R @@ -1,13 +1,19 @@ -#' Show the `qenv` object +#' Display `qenv` Object +#' +#' Prints the `qenv` object. #' -#' Prints the `qenv` object #' @param object (`qenv`) -#' @return nothing -#' @importFrom methods show +#' +#' @return `object`, invisibly. +#' #' @examples #' q <- qenv() #' q1 <- eval_code(q, expression(a <- 5, b <- data.frame(x = 1:10))) #' q1 +#' +#' @aliases show-qenv +#' +#' @importFrom methods show #' @export setMethod("show", "qenv", function(object) { rlang::env_print(object@env) diff --git a/R/qenv-within.R b/R/qenv-within.R index 03a02823..4302a59f 100644 --- a/R/qenv-within.R +++ b/R/qenv-within.R @@ -1,34 +1,28 @@ -#' Evaluate expression in `qenv` object. +#' Evaluate Expression in `qenv` #' -#' Convenience function for evaluating inline code inside the environment of a `qenv`. +#' @details +#' `within` is a convenience function for evaluating inline code inside the environment of a `qenv`. +#' It is a method for the `base` generic that wraps `eval_code` to provide a simplified way of passing code. +#' `within` accepts only inline expressions (both simple and compound) and allows for injecting values into `expr` +#' through the `...` argument: +#' as `name:value` pairs are passed to `...`, `name` in `expr` will be replaced with `value`. #' -#' This is a wrapper for `eval_code` that provides a simplified way of passing code for evaluation. -#' It accepts only inline expressions (both simple and compound) and allows for injecting values into `expr` -#' through the `...` argument: as `name:value` pairs are passed to `...`, -#' `name` in `expr` will be replaced with `value`. -#' -#' @section Using language objects: +#' @section Using language objects with `within`: #' Passing language objects to `expr` is generally not intended but can be achieved with `do.call`. #' Only single `expression`s will work and substitution is not available. See examples. #' -#' @param data `qenv` object -#' @param expr `expression` to evaluate -#' @param ... `name:value` pairs to inject values into `expr` +#' @param data (`qenv`) +#' @param expr (`expression`) to evaluate. Must be inline code, see `Using language objects...` +#' @param ... see `Details` #' #' @return -#' Returns a `qenv` object with `expr` evaluated. If evaluation raises an error, a `qenv.error` is returned. -#' -#' @seealso [`eval_code`], [`base::within`] +#' `within` returns a `qenv` object with `expr` evaluated or `qenv.error` if evaluation fails. #' -#' @export -#' -#' @rdname within +#' @seealso [`base::within`] #' #' @examples -#' +#' # evaluate code using within #' q <- qenv() -#' -#' # execute code #' q <- within(q, { #' i <- iris #' }) @@ -57,6 +51,10 @@ #' within(q, exprlist) # fails #' do.call(within, list(q, do.call(c, exprlist))) #' +#' @rdname qenv +#' +#' @export +#' within.qenv <- function(data, expr, ...) { expr <- substitute(expr) extras <- list(...) diff --git a/man/concat.Rd b/man/concat.Rd index 6664e678..2954d121 100644 --- a/man/concat.Rd +++ b/man/concat.Rd @@ -5,15 +5,9 @@ \alias{concat,qenv,qenv-method} \alias{concat,qenv.error,ANY-method} \alias{concat,qenv,qenv.error-method} -\title{Concatenate two \code{qenv} objects} +\title{Concatenate Two \code{qenv} Objects} \usage{ concat(x, y) - -\S4method{concat}{qenv,qenv}(x, y) - -\S4method{concat}{qenv.error,ANY}(x, y) - -\S4method{concat}{qenv,qenv.error}(x, y) } \arguments{ \item{x}{(\code{qenv})} @@ -25,6 +19,8 @@ concat(x, y) } \description{ Combine two \code{qenv} objects by simple concatenate their environments and the code. +} +\details{ We recommend to use the \code{join} method to have a stricter control in case \code{x} and \code{y} contain duplicated bindings and code. RHS argument content has priority over the LHS one. @@ -37,4 +33,5 @@ q1 <- eval_code(q1, "iris2 <- iris") q2 <- eval_code(q2, "mtcars2 <- mtcars") qq <- concat(q1, q2) get_code(qq) + } diff --git a/man/eval_code.Rd b/man/eval_code.Rd deleted file mode 100644 index 6b7a6703..00000000 --- a/man/eval_code.Rd +++ /dev/null @@ -1,40 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/qenv-eval_code.R -\name{eval_code} -\alias{eval_code} -\alias{eval_code,qenv,character-method} -\alias{eval_code,qenv,language-method} -\alias{eval_code,qenv,expression-method} -\alias{eval_code,qenv.error,ANY-method} -\title{Evaluate the code in the \code{qenv} environment} -\usage{ -eval_code(object, code) - -\S4method{eval_code}{qenv,character}(object, code) - -\S4method{eval_code}{qenv,language}(object, code) - -\S4method{eval_code}{qenv,expression}(object, code) - -\S4method{eval_code}{qenv.error,ANY}(object, code) -} -\arguments{ -\item{object}{(\code{qenv})} - -\item{code}{(\code{character} or \code{language}) code to evaluate. Also accepts and stores comments} -} -\value{ -\code{qenv} object. -} -\description{ -Given code is evaluated in the \code{qenv} environment and appended to the \code{code} slot. This means -that state of the environment is always a result of the stored code (if \code{qenv} was initialized) -with reproducible code. -} -\examples{ -q <- qenv() -q1 <- eval_code(q, quote(a <- 1)) -q2 <- eval_code(q1, quote(library(checkmate))) -q3 <- eval_code(q2, quote(assert_number(a))) - -} diff --git a/man/get_code.Rd b/man/get_code.Rd deleted file mode 100644 index 559619af..00000000 --- a/man/get_code.Rd +++ /dev/null @@ -1,35 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/qenv-get_code.R -\name{get_code} -\alias{get_code} -\alias{get_code,qenv-method} -\alias{get_code,qenv.error-method} -\title{Get code from \code{qenv}} -\usage{ -get_code(object, deparse = TRUE, ...) - -\S4method{get_code}{qenv}(object, deparse = TRUE) - -\S4method{get_code}{qenv.error}(object, deparse = TRUE, ...) -} -\arguments{ -\item{object}{(\code{qenv})} - -\item{deparse}{(\code{logical(1)}) if the returned code should be converted to character.} - -\item{...}{arguments passed to methods.} -} -\value{ -named \code{character} with the reproducible code. -} -\description{ -Get code from \code{qenv} -} -\examples{ -q <- qenv() -q1 <- eval_code(q, code = quote(a <- 1)) -q2 <- eval_code(q1, code = quote(b <- a)) -q3 <- eval_code(q2, code = quote(d <- 2)) -get_code(q3) -get_code(q3, deparse = FALSE) -} diff --git a/man/get_var.Rd b/man/get_var.Rd index 9ad3b4c2..35f922a3 100644 --- a/man/get_var.Rd +++ b/man/get_var.Rd @@ -4,38 +4,23 @@ \alias{get_var} \alias{get_var,qenv,character-method} \alias{get_var,qenv.error,ANY-method} -\alias{[[,qenv,ANY,missing-method} -\alias{[[.qenv.error} -\title{Get object from the \code{qenv} environment} +\alias{[[,qenv-method} +\title{Get Object From \code{qenv}} \usage{ get_var(object, var) -\S4method{get_var}{qenv,character}(object, var) - -\S4method{get_var}{qenv.error,ANY}(object, var) - -\S4method{[[}{qenv,ANY,missing}(x, i, j, ...) - -\method{[[}{qenv.error}(x, i, j, ...) +\S4method{[[}{qenv}(x, i) } \arguments{ -\item{object}{(\code{qenv})} - -\item{var}{(\code{character(1)}) name of the variable to pull from the environment.} - -\item{x}{(\code{qenv})} - -\item{i}{(\code{character}) name of the binding in environment (name of the variable)} - -\item{j}{not used} +\item{object, x}{(\code{qenv})} -\item{...}{not used} +\item{var, i}{(\code{character(1)}) variable name.} } \value{ The value of required variable (\code{var}) within \code{qenv} object. } \description{ -Get object from the \code{qenv} environment. +Retrieve variables from the \code{qenv} environment. } \examples{ q <- qenv() diff --git a/man/get_warnings.Rd b/man/get_warnings.Rd index 77c1d060..07e5f7a6 100644 --- a/man/get_warnings.Rd +++ b/man/get_warnings.Rd @@ -2,27 +2,21 @@ % Please edit documentation in R/qenv-get_warnings.R \name{get_warnings} \alias{get_warnings} -\alias{get_warnings,qenv.error-method} \alias{get_warnings,qenv-method} +\alias{get_warnings,qenv.error-method} \alias{get_warnings,NULL-method} -\title{Get the warnings of \code{qenv} object} +\title{Get Warnings From \code{qenv} Object} \usage{ get_warnings(object) - -\S4method{get_warnings}{qenv.error}(object) - -\S4method{get_warnings}{qenv}(object) - -\S4method{get_warnings}{`NULL`}(object) } \arguments{ \item{object}{(\code{qenv})} } \value{ -\code{character} containing warning information or \code{NULL} if no warnings +\code{character} containing warning information or \code{NULL} if no warnings. } \description{ -Get the warnings of \code{qenv} object +Retrieve all warnings raised during code evaluation in a \code{qenv}. } \examples{ data_q <- qenv() @@ -32,4 +26,5 @@ warning_qenv <- eval_code( bquote(p <- hist(iris_data[, .("Sepal.Length")], ff = "")) ) cat(get_warnings(warning_qenv)) + } diff --git a/man/join.Rd b/man/join.Rd index 59bb0356..44aad1c4 100644 --- a/man/join.Rd +++ b/man/join.Rd @@ -3,17 +3,11 @@ \name{join} \alias{join} \alias{join,qenv,qenv-method} -\alias{join,qenv.error,ANY-method} \alias{join,qenv,qenv.error-method} -\title{Join two \code{qenv} objects} +\alias{join,qenv.error,ANY-method} +\title{Join \code{qenv} Objects} \usage{ join(x, y) - -\S4method{join}{qenv,qenv}(x, y) - -\S4method{join}{qenv.error,ANY}(x, y) - -\S4method{join}{qenv,qenv.error}(x, y) } \arguments{ \item{x}{(\code{qenv})} @@ -24,12 +18,13 @@ join(x, y) \code{qenv} object. } \description{ -\code{join()} perform checks and merges two \code{qenv} objects into one \code{qenv} object. +Checks and merges two \code{qenv} objects into one \code{qenv} object. +} +\details{ Any common code at the start of the \code{qenvs} is only placed once at the start of the joined \code{qenv}. This allows consistent behavior when joining \code{qenvs} which share a common ancestor. See below for an example. -} -\details{ + There are some situations where \code{join()} cannot be properly performed, such as these three scenarios: \enumerate{ \item Both \code{qenv} objects contain an object of the same name but are not identical. \cr\cr diff --git a/man/qenv.Rd b/man/qenv.Rd index e3190427..c8f4f4a5 100644 --- a/man/qenv.Rd +++ b/man/qenv.Rd @@ -1,5 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/qenv-constructor.R +% Please edit documentation in R/qenv-constructor.R, R/qenv-eval_code.R, +% R/qenv-get_code.R, R/qenv-within.R \name{qenv} \alias{qenv} \alias{new_qenv} @@ -8,32 +9,81 @@ \alias{new_qenv,environment,language-method} \alias{new_qenv,environment,missing-method} \alias{new_qenv,missing,missing-method} -\title{Initialize \code{qenv} object} +\alias{eval_code} +\alias{eval_code,qenv,character-method} +\alias{eval_code,qenv,language-method} +\alias{eval_code,qenv,expression-method} +\alias{eval_code,qenv.error,ANY-method} +\alias{get_code} +\alias{get_code,qenv-method} +\alias{get_code,qenv.error-method} +\alias{within.qenv} +\title{Code Tracking With \code{qenv} Object} \usage{ qenv() new_qenv(env = new.env(parent = parent.env(.GlobalEnv)), code = character()) + +eval_code(object, code) + +get_code(object, deparse = TRUE, ...) + +\method{within}{qenv}(data, expr, ...) } \arguments{ \item{env}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} (\code{environment}) Environment being a result of the \code{code} evaluation.} -\item{code}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} -(\code{character(1)} or \code{language}) code to evaluate. Accepts and stores comments also.} +\item{code}{(\code{character} or \code{language}) code to evaluate. If \code{character}, comments are retained.} + +\item{object}{(\code{qenv})} + +\item{deparse}{(\code{logical(1)}) flag specifying whether to return code as \code{character} or \code{expression}.} + +\item{...}{see \code{Details}} + +\item{data}{(\code{qenv})} + +\item{expr}{(\code{expression}) to evaluate. Must be inline code, see \verb{Using language objects...}} } \value{ -\code{qenv} object. +\code{qenv} and \code{new_qenv} return a \code{qenv} object. + +\code{eval_code} returns a \code{qenv} object with \code{expr} evaluated or \code{qenv.error} if evaluation fails. + +\code{get_code} returns the traced code (from \verb{@code} slot) in the form specified by \code{deparse}. + +\code{within} returns a \code{qenv} object with \code{expr} evaluated or \code{qenv.error} if evaluation fails. } \description{ -Create an empty \code{qenv} object. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} + +Create a \code{qenv} object and evaluate code in it to track code history. } \details{ \code{qenv()} instantiates a \code{qenv} with an empty environment. Any changes must be made by evaluating code in it with \code{eval_code} or \code{within}, thereby ensuring reproducibility. -\code{new_qenv()} (deprecated and not recommended) +\code{new_qenv()} (\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} and not recommended) can instantiate a \code{qenv} object with data in the environment and code registered. + +\code{eval_code} evaluates given code in the \code{qenv} environment and appends it to the \code{code} slot. +Thus, if the \code{qenv} had been instantiated empty, contents of the environment are always a result of the stored code. + +\code{get_code} retrieves the code stored in the \code{qenv}. \code{...} passes arguments to methods. + +\code{within} is a convenience function for evaluating inline code inside the environment of a \code{qenv}. +It is a method for the \code{base} generic that wraps \code{eval_code} to provide a simplified way of passing code. +\code{within} accepts only inline expressions (both simple and compound) and allows for injecting values into \code{expr} +through the \code{...} argument: +as \code{name:value} pairs are passed to \code{...}, \code{name} in \code{expr} will be replaced with \code{value}. +} +\section{Using language objects with \code{within}}{ + +Passing language objects to \code{expr} is generally not intended but can be achieved with \code{do.call}. +Only single \code{expression}s will work and substitution is not available. See examples. } + \examples{ # create empty qenv qenv() @@ -43,4 +93,49 @@ new_qenv(env = list2env(list(a = 1)), code = quote(a <- 1)) new_qenv(env = list2env(list(a = 1)), code = parse(text = "a <- 1", keep.source = TRUE)) new_qenv(env = list2env(list(a = 1)), code = "a <- 1") +# evaluate code in qenv +q <- qenv() +q <- eval_code(q, "a <- 1") +q <- eval_code(q, quote(library(checkmate))) +q <- eval_code(q, expression(assert_number(a))) + +# retrieve code +get_code(q) +get_code(q, deparse = FALSE) + +# evaluate code using within +q <- qenv() +q <- within(q, { + i <- iris +}) +q <- within(q, { + m <- mtcars + f <- faithful +}) +q +get_code(q) + +# inject values into code +q <- qenv() +q <- within(q, i <- iris) +within(q, print(dim(subset(i, Species == "virginica")))) +within(q, print(dim(subset(i, Species == species)))) # fails +within(q, print(dim(subset(i, Species == species))), species = "versicolor") +species_external <- "versicolor" +within(q, print(dim(subset(i, Species == species))), species = species_external) + +# pass language objects +expr <- expression(i <- iris, m <- mtcars) +within(q, expr) # fails +do.call(within, list(q, expr)) + +exprlist <- list(expression(i <- iris), expression(m <- mtcars)) +within(q, exprlist) # fails +do.call(within, list(q, do.call(c, exprlist))) + +} +\seealso{ +\code{\link[=get_var]{get_var()}}, \code{\link[=get_warnings]{get_warnings()}}, \code{\link[=join]{join()}}, \code{\link[=concat]{concat()}} + +\code{\link[base:with]{base::within}} } diff --git a/man/show-qenv-method.Rd b/man/show-qenv-method.Rd index 1df4b51a..095cc896 100644 --- a/man/show-qenv-method.Rd +++ b/man/show-qenv-method.Rd @@ -2,7 +2,8 @@ % Please edit documentation in R/qenv-show.R \name{show,qenv-method} \alias{show,qenv-method} -\title{Show the \code{qenv} object} +\alias{show-qenv} +\title{Display \code{qenv} Object} \usage{ \S4method{show}{qenv}(object) } @@ -10,13 +11,14 @@ \item{object}{(\code{qenv})} } \value{ -nothing +\code{object}, invisibly. } \description{ -Prints the \code{qenv} object +Prints the \code{qenv} object. } \examples{ q <- qenv() q1 <- eval_code(q, expression(a <- 5, b <- data.frame(x = 1:10))) q1 + } diff --git a/man/within.Rd b/man/within.Rd deleted file mode 100644 index a27c1d17..00000000 --- a/man/within.Rd +++ /dev/null @@ -1,70 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/qenv-within.R -\name{within.qenv} -\alias{within.qenv} -\title{Evaluate expression in \code{qenv} object.} -\usage{ -\method{within}{qenv}(data, expr, ...) -} -\arguments{ -\item{data}{\code{qenv} object} - -\item{expr}{\code{expression} to evaluate} - -\item{...}{\code{name:value} pairs to inject values into \code{expr}} -} -\value{ -Returns a \code{qenv} object with \code{expr} evaluated. If evaluation raises an error, a \code{qenv.error} is returned. -} -\description{ -Convenience function for evaluating inline code inside the environment of a \code{qenv}. -} -\details{ -This is a wrapper for \code{eval_code} that provides a simplified way of passing code for evaluation. -It accepts only inline expressions (both simple and compound) and allows for injecting values into \code{expr} -through the \code{...} argument: as \code{name:value} pairs are passed to \code{...}, -\code{name} in \code{expr} will be replaced with \code{value}. -} -\section{Using language objects}{ - -Passing language objects to \code{expr} is generally not intended but can be achieved with \code{do.call}. -Only single \code{expression}s will work and substitution is not available. See examples. -} - -\examples{ - -q <- qenv() - -# execute code -q <- within(q, { - i <- iris -}) -q <- within(q, { - m <- mtcars - f <- faithful -}) -q -get_code(q) - -# inject values into code -q <- qenv() -q <- within(q, i <- iris) -within(q, print(dim(subset(i, Species == "virginica")))) -within(q, print(dim(subset(i, Species == species)))) # fails -within(q, print(dim(subset(i, Species == species))), species = "versicolor") -species_external <- "versicolor" -within(q, print(dim(subset(i, Species == species))), species = species_external) - -# pass language objects -expr <- expression(i <- iris, m <- mtcars) -within(q, expr) # fails -do.call(within, list(q, expr)) - -exprlist <- list(expression(i <- iris), expression(m <- mtcars)) -within(q, exprlist) # fails -do.call(within, list(q, do.call(c, exprlist))) - -} -\seealso{ -\code{\link{eval_code}}, \code{\link[base:with]{base::within}} -}