COLOR(red){SIZE(30){R でマクロを実現する関数}}
// 間瀬 2003/7/11

次の関数 COLOR(red){defmacro} はパラメータ付きのマクロを定義する。C 言語に慣れ
た人には便利かも知れない。この関数の本来の目的は、~
複数の関数で(幾つかのパラメータ値を除いて)同一の部分をマクロにしておき、コードを簡潔かつ統一的にすることである。

注:マクロは実行時に定義内容がコード中にまず展開され、その後実行される。

#contents

*関数のコード
 
 defmacro <- function(..., expr) {
  # ... には任意個のパラメータ引数 (零個不可)、expr には R の表現式
  # by T. Lumley, in "Macros in R" in Rnwes, Vol. 1/3, Sep. (2001) より              
  # 使用例                                                                                                            
  # mcr <- defmacro(x, y, expr=x*exp(y))  # パラメータ x, y を持つマクロ定義     
  # foo <- function (x) x*mcr(2, 3)   # foo は x*2*exp(3) になる                             
 # 
  expr <- substitute(expr)
   a <- substitute(list(...))[-1]
   nn <- names(a)
   if (is.null(nn)) nn <- rep("", length(a))
   for (i in seq(length = length(a))) {
     if (nn[i] == "") {
       nn[[i]] <- paste(a[[i]])
       msg <- paste(a[[i]], "not supplied")
       a[[i]] <- substitute(stop(foo), list(foo = msg))
     }
   }
   names(a) <- nn
   a <- as.list(a)
   ff <- eval(substitute(
                function () {
                  tmp <- substitute(body)
                  eval(tmp, parent.frame())
                }, list(body = expr)))
   formals(ff) <- a
   mm <- match.call()
   mm$expr <- NULL
   mm[[1]] <- as.name("macro")
   attr(ff, "source") <- c(deparse(mm), deparse(expr))
   ff
 }

*使用例

 > mcr <- defmacro(a, expr=readline("Input a number -> "))  # a はダミーパラメータ
 > mcr(0)  # パラメータ 0 は無意味
 Input a number -> 3
 [1] "3"
 > foo <- function (x)  x + as.numeric(mcr(0))   # mcr(0) の返す値は文字列なので数値化
 > foo(4)
 Input a number -> 5
 [1] 9   # 4 + 5

 > mcr <- defmacro(x, y, expr=exp(x)*sin(y))  # パラメータが二個のマクロ
 > mcr              # マクロの定義内容
 macro(x, y)
 exp(x) * sin(y)
 <environment: 0x9065944>
 > mcr(2, 3)      # マクロを単独で実行(まるで関数そのものに見える)
 [1] 1.042744
 > foo <- function (x) x*mcr(2, 3)
 > foo(1)
 [1] 1.042744    # 1*exp(2)*sin(3)

 > mcr <- defmacro(i, j, k, expr=i*(j+k))
 > mcr(2,3,4)
 [1] 14

これだけなら関数で足りること。マクロでなくちゃというもう少し気の効いた例はないものか?

*コメント 1
次の例は,関数を使わない方が好ましい例かもしれません。

こんなことをしなくてもと思う場合には,
 jugemujugemugokounosurikire <- jugemujugemugookounosurikire*(kaijarisuigyo+3)
みたいな例((左辺の変数は右辺の長い変数と同じつもりをタイプミスした例))をわざわざ挙げたり。

C 言語みたいに +<-,-<-, *<-, /<- みたいなの((C 言語などでは, x *= y+1 は,x = x*(y+1) と同じことを表す代入演算子))があれば((割り込みコメント。[[二項演算子定義の例]] を参照して下さい。))いいのだけど。

 > mul  <- defmacro(x, y, expr=x <- x*(y))
 > x <- 2
 > y <- 4
 > mul(x, y+1)
 > x
 [1] 10

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS