Reputation: 1313
I'd like to wrap around the checkmate
library's qassert
to check multiple variable's specification at a time. Importantly, I'd like assertion errors to still report the variable name that's out of spec.
So I create checkargs
to loop through input arguments. But to get the variable passed on to qassert
, I use the same code for each loop -- that ambigious code string gets used for for the error message instead of the problematic variable name.
qassert()
(via vname()
) is getting what to display in the assertion error like deparse(eval.parent(substitute(substitute(x)))
. Is there any way to box up get(var)
such that that R will see e.g. 'x' on deparse instead?
At least one work around is eval(parse())
. But something like checkargs(x="n', system('echo malicious',intern=T),'")
has me hoping for an alternative.
checkargs <- function(...) {
args<-list(...)
for(var in names(args))
checkmate::qassert(get(var,envir=parent.frame()),args[[var]])
# scary string interpolation alternative
#eval(parse(text=paste0("qassert(",var,",'",args[[var]], "')")),parent.frame())
}
test_checkargs <- function(x, y) {checkargs(x='b',y='n'); print(y)}
# checkargs is working!
test_checkargs(T, 1)
# [1] 1
# but the error message isn't helpful.
test_checkargs(1, 1)
# Error in checkargs(x = "b", y = "n") :
# Assertion on 'get(var, envir = parent.frame())' failed. Must be of class 'logical', not 'double'.
#
# want:
# Assertion on 'x' failed. ...
Upvotes: 0
Views: 98
Reputation: 1313
substitute()
with as.name
seems to do the trick. This still uses eval
but without string interpolation.
eval(substitute(
qassert(x,spec),
list(x=as.name(var),
spec=args[[var]])),
envir=parent.frame())
Upvotes: 1