egnha / valaddin

Functional input validation to make R functions more readable and robust
Other
33 stars 1 forks source link

Check item scope must be distinct from the scope of ambient formula #38

Closed egnha closed 7 years ago

egnha commented 7 years ago

When creating a firm closure, say

foo <- firmly(f, list(check_item) ~ predicate)

the predicate function is to be evaluated in the environment of the formula list(check_item) ~ predicate.

The scope of evaluation of the right-hand side of the formula check_item is a bit more delicate: the environment of the rhs of check_item must be in scope, with precedence given, however, to arguments of f, which are then found in an isolated (temporary) environment of promise objects. (In the “Tidy Evaluation” framework, we would say that the arguments overscope the context of the check item.)

Thus, when validating a check item, three environments are in play:

  1. An environment of promises (the arguments of f as they are called).
  2. The environment of check_item.
  3. The environment of the formula list(check_item) ~ predicate.

These are generally not linearly ordered, so creating the proper transformation of the validation expression, and the proper environment in which to evaluate it, requires care. Thus, check_item is a quosure, in the tidy-eval sense.

One approach to ensuring that the validation occurs with the proper lexical scoping is as follows:

For example, if we were to do this

a <- 1
is_positive <- function(.) . > 0
foo <- firmly(function(x) NULL, list(~x - a) ~ is_positive)

then the validation of the condition “is_positive(x - a)” should be translated to something like

`__PREDICATE__`(get("x", envir = `__PROMISES__`) - a)

and evaluated in an environment containing exactly two bindings, __PREDICATE__, __PROMISES__, and whose parent is the environment of the check item ~x - a. The binding __PREDICATE__ gets the predicate function is_positive, while the binding __PROMISES__ gets a (temporary) environment of promises of f.

In this example, the environment of the check item and the environment of the ambient formula are identical; in general, however, they could be quite different, e.g., localized check makers created in a package should not, when called, endow their check items with the same environment.

Alternative approach Keep the current validation-evaluation framework as is, but allow check items to be quosures, cf. #39.

egnha commented 7 years ago