Is it safe to use macros in R? -
i have written macros in r using defmacro
function gtools
package:
#' iflen macro #' #' check whether object has non-zero length, , #' eval expression accordingly. #' #' @param df object can passed \code{length} #' @param body1 if \code{length(df)} not zero, clause evaluated, otherwise, body2 evaluated. #' @param body2 see above. #' @importfrom gtools defmacro #' #' @examples #' iflen(c(1, 2), { print('yes!') }, {print("no!")}) #' #' @author kaiyin #' @export iflen = gtools::defmacro(df, body1, body2 = {}, expr = { if(length(df) != 0) { body1 } else { body2 } }) #' iflet macro #' #' eval expression x, assign variable, , if true, continue #' eval expression1, otherwise eval expression2. inspired clojure #' \code{if-let} macro. #' #' @param sym_str string converted symbol hold value of \code{x} #' @param x predicate evalueated, , assigned temporary variable described in \code{sym_str} #' @param body1 expression evaluated when temporary variable true. #' @param body2 expression evaluated when temporary variable false. #' @importfrom gtools defmacro #' #' @examples #' iflet("..temp..", true, {print(paste("true.", as.character(..temp..)))}, #' {print(paste("false.", as.character(..temp..)))}) #' #' @author kaiyin #' @export iflet = gtools::defmacro(sym_str, x, body1, body2={}, expr = { stopifnot(is.character(sym_str)) stopifnot(length(sym_str) == 1) assign(sym_str, x) if(eval(as.symbol(sym_str))) { body1 } else { body2 } }) #' ifletlen macro #' #' similar iflet, conditioned on whether length of #' result of \code{eval(x)} 0. #' #' #' @param x predicate evalueated, , assigned temporary var called \code{..temp..} #' @param body1 expression evaluated when \code{..temp..} true. #' @param body2 expression evaluated when \code{..temp..} false. #' @importfrom gtools defmacro #' #' @examples #' ifletlen("..temp..", 1:3, {print(paste("true.", as.character(..temp..)))}, #' {print(paste("false.", as.character(..temp..)))}) #' #' @author kaiyin #' @export ifletlen = gtools::defmacro(sym_str, x, body1, body2={}, expr = { stopifnot(is.character(sym_str)) stopifnot(length(sym_str) == 1) assign(sym_str, x) iflen(eval(as.symbol(sym_str)), { body1 }, { body2 }) })
is there danger in using them?
of course have careful. macros not have own environments.
simple example f(x,y) = (x+y)^2:
m1 <- defmacro(x, y, expr = { x <- x + y x*x })
executing m1
change input variables in calling environment:
> x <- 1 > y <- 2 > m1(x, y) [1] 9 > x [1] 3 > y [1] 2
normal r functions behave differently:
f1 <- function(x, y) { x <- x + y x*x } > x <- 1 > y <- 2 > f1(x, y) [1] 9 > x [1] 1 > y [1] 2
Comments
Post a Comment