如何解决在 R 函数体中搜索特定行
我希望在函数体的特定点“复制和修改”一个函数。目前,我拥有的是
nearest_psd <- function(mat) {
ed <- eigen(mat)
eigvecs <- ed$vectors
eigvals <- ed$values
eigvals[eigvals<0] <- 0
eigvecs %*% diag(eigvals) %*% t(eigvecs)
}
nearest_pd <- nearest_psd
formals(nearest_pd)$pdeps <- 1e-08
body(nearest_pd)[[c(7,3)]] <- quote(pdeps)
,所以 nearest_pd
是 nearest_psd
的副本,除了 eigvals[eigvals<0] <- pdeps
行。
但是,行号(在本例中为 7)是硬编码的,我更希望有一种可靠的方法来确定此行号。如何搜索包含表达式 eigvals[eigvals<0] <- 0
的行?
解决方法
你可以使用identical
来比较两个表达式;这样,您就可以识别并替换有问题的表达式:
to_replace = vapply(body(nearest_pd),function (e) identical(e,quote(eigvals[eigvals < 0] <- 0)),logical(1L))
body(nearest_pd)[to_replace] = list(quote(eigvals[eigvals < pdeps] <- pdeps))
然而,这并不比您的代码更易读,也更健壮:在这两种情况下,您都被迫对相关信息进行硬编码;在您的代码中,索引。在我的,表达。出于这个原因,我不建议使用它。
... 当然,您可以改为使用 AST walker 将函数主体中所有出现的 0
替换为 pdeps
。但这样更好吗?不可以,因为 0
可用于其他目的。 目前不是,但谁知道,一旦原始功能发生变化。如果不能假设原始函数发生变化,为什么不完全硬编码新函数呢?也就是这样写:
nearest_pd <- function (mat,pdeps = 1e-08) {
ed <- eigen(mat)
eigvecs <- ed$vectors
eigvals <- ed$values
eigvals[eigvals < pdeps] <- pdeps
eigvecs %*% diag(eigvals) %*% t(eigvecs)
}
……不需要仅仅为了它而使用元编程。
,以下内容可能会满足您的需求。
nearest_psd <- function(mat) {
ed <- eigen(mat)
eigvecs <- ed$vectors
eigvals <- ed$values
eigvals[eigvals<0] <- 0
eigvecs %*% diag(eigvals) %*% t(eigvecs)
}
nearest_pd <- nearest_psd
formals(nearest_pd)$pdeps <- 1e-08
nearest_psd_body <- body(nearest_psd)
# Find the string we a re looking for and replace it ...
new.code <- gsub("eigvals[eigvals < 0] <- 0","MY_NEW_CODE",nearest_psd_body,fixed = TRUE)
# Buidling the function body as a string.
new.code <- new.code[-1] # delete first { such that ...
new.code <- paste(new.code,collapse = ";") # we can collapse the remaining here ....
new.code <- paste("{",new.code,"}",sep = "",collapse = "") # and then wrap the remaining in { }
# parse returns an expression.
body(nearest_pd) <- parse(text = new.code)
有关 parse
的解释,请参阅 At a basic level,what does eval-parse do in R?。或者 In programming,what is an expression? 表达式是什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。