我想检查以下字符串是否是有效的数学表达式:
s1 = 'sin(x)'
s2 = 'sin(x*m)'
s3 = 'sin'
s4 = 'sin(xm)'
通过“有效”,我的意思是表达式是
- 运算符(必须与变量或常量一起使用)
- 变量
x
和/或m
- 常数。
根据这个定义s1
,ands2
是有效的,而s3
不是s4
。
为了识别字符串是否有效,我编写了一个函数checkFxn
,首先尝试将字符串转换为调用或其一部分。如果成功,它将通过调用树递归并检查上述条件。如果满足条件,则按原样返回调用。如果不是,则抛出错误。
checkFxn <- function(x) {
lang <- str2lang(x)
checkFxn2 <- function(y) {
if(is.name(y)) {
stopifnot(deparse(y) %in% c('x', 'm'))
} else if(is.call(y)) {
stopifnot(is.function(eval(y[[1]])) | is.primitive(eval(y[[1]])))
lapply(y[-1], checkFxn2)
} else {
stopifnot(is.logical(y) | is.numeric(y) | is.complex(y))
}
return(y)
}
checkFxn2(lang)
}
#Applying checkFxn to s1-4
lapply(list(s1,s2,s3,s4), function(x) {try(checkFxn(x), silent = T)})
[[1]]
sin(x)
[[2]]
sin(x * m)
[[3]]
[1] "Error in checkFxn2(lang) : deparse(y) %in% c(\"x\", \"m\") is not TRUE\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in checkFxn2(lang): deparse(y) %in% c("x", "m") is not TRUE>
[[4]]
[1] "Error in FUN(X[[i]], ...) : deparse(y) %in% c(\"x\", \"m\") is not TRUE\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in FUN(X[[i]], ...): deparse(y) %in% c("x", "m") is not TRUE>
它似乎按预期工作,但我对我的使用持谨慎态度,eval
并想知道是否有人可以建议使用它的替代方法?我知道它遵循通常的词法范围规则,所以我担心它会在 gobal 环境中评估变量——有没有办法限制它的范围?我已经阅读了关于非标准评估的章节,但我无法弄清楚。
另外,有没有办法确定基函数或原语是否是数学运算符?我想使用比is.function
and更具体的东西is.primitive
。