assertthat
我经常使用这个包来检查函数中的后置条件。在阅读有关按合同设计的想法的更多信息时,我偶然发现了将输出与输入值进行比较的想法。
最简单的例子如下:
toggle <- function(x)!x
人们可以立即声明这x == !old_x
必须始终为真。(old_x
代表x
评估前的值。)
(当然这个例子过于简单了,后置条件并没有为人类或计算机添加更多有用的信息。一个更有用的例子在问题的底部..)
因此,我可以toggle
按如下方式扩展我的函数,以便在每次调用时检查该条件:
toggle <- function(x){
old_x <- x
x <- !x
assertthat::assert_that(x == !old_x)
return(x)
}
这当然可行,但我想知道是否有另一种方法可以访问 的值,old_x
而无需以新名称显式存储它(或结果)。并且无需将后置条件检查代码拆分到函数的顶部和底部。类似于 R 评估函数调用的方式。
我能想到的一种尝试是使用sys.call
和eval.parent
访问旧值:
toggle <- function(x){
x <- !x
.x <- eval.parent(as.list(sys.call())[[2]])
assertthat::assert_that(x == !.x)
return(x)
}
这可行,但我仍然需要分配一个新变量.x
,而且子集[[2]]
还不灵活。然而,像这样写是assertthat::assert_that(x == !eval.parent(as.list(sys.call())[[2]])
行不通的,并且玩弄搜索级别sys.call(-1 ..)
也无济于事。
后置条件添加一些信息的另一个(更有用的)示例:
increment_if_smaller_than_2 <- function(x){
old_x <- x
x <- ifelse(x < 2, x <- x + 1, x)
assertthat::assert_that(all(x >= old_x))
return(x)
}
有什么提示吗?