在C中,宏就像一个函数,但在编译之前,宏调用的任何示例都被宏的文本替换。
我的用例是这样的:
floor_dec <- function(x, sigDig=1) {
if (x == 0) {return(x)}
if (is.infinite(x)) {return(x)}
if (sigDig <= 0) {stop("Error: sigDig must be a positive integer.")}
sigDig = round(sigDig)
mostSig = ceiling(log10(abs(x)))
floor(x*10^(sigDig-mostSig))*10^-(sigDig-mostSig)
}
ceil_dec <- function(x, sigDig=1) {
if (x == 0) {return(x)} # This feels familiar
if (is.infinite(x)) {return(x)} # So does this...
if (sigDig <= 0) {stop("Error: sigDig must be a positive integer.")} # Wait a minute
sigDig = round(sigDig)
mostSig = ceiling(log10(abs(x)))
ceiling(x*10^(sigDig-mostSig))*10^-(sigDig-mostSig)
}
这两个函数的参数检查部分是完全相同的,所以我想写一次,然后只引用它。问题是我不能把代码直接放进另一个函数。内部函数需要使用一个sentinel变量来通知外部函数提前返回,另一个变量来存储我要返回的值。
我的第一个方法是gtools::defmacro
,但它似乎没有达到我想要的效果,似乎和其他函数一样。接下来我尝试使用这样的替换:
.check_dec_parameters <- substitute({
if (x == 0) {return(x)}
if (is.infinite(x)) {return(x)}
if (sigDig <= 0) {stop("Error: sigDig must be a positive integer.")}
})
ceil_dec <- function(x, sigDig=1) {
eval(.check_dec_parameters)
sigDig = round(sigDig)
mostSig = ceiling(log10(abs(x)))
ceiling(x*10^(sigDig-mostSig))*10^-(sigDig-mostSig)
}
但是.check_dec_parameters
中的返回似乎不是从外部函数返回的。stop()
工作正常,所以我猜已经完成了一半。谁能告诉我如何到达最后,可能是解释一下?我正在阅读http://adv-r.had.co.nz/Expressions.html,看看我可能遗漏了什么。
3条答案
按热度按时间vwoqyblh1#
另一种方法是使用function operator来添加参数检查:
结果:
cclgggtu2#
R允许在语言上进行计算,但它与宏文本替换不同。如果没有函数上下文,您无法从
eval
“返回”。另一种策略是创建 Package 器。例如,您可以这样做n6lpvg4x3#
返回函数的函数有一个警告,即被调用和返回的函数将具有不同的求值环境,除非您另外安排对
environment<-
的适当调用。为了避免这些类型的陷阱,只需定义一个包含“宏”和
substitute
的模板函数到主体中:另一个选项是
bquote
,它在后台做同样的事情:这两种方法都应该感觉(至少在概念上)更接近于使用C预处理器宏,基于将符号替换为代码片段。