2017-03-30 6 views
1

カスタム仮引数名で関数を作るために関数ファクトリを作ろうとしています。この考え方は、文字列をファクトリに供給し、ファクトリと返される関数の本文の両方に文字列を代入します。私はそれをeval(parse(text = paste()))を使ってやっていましたが、私はこの悪い習慣をどこかで読んでいます。どのようにevalparseを避けながら同じ出力を得ることができますか?関数ファクトリで仮引数を代入するr

MyLinearRateFunctions<-function(varX){ 

    eval(parse(text=paste("function(a,b,", 
        varX, 
        ") 1/(a + b*", 
        varX, 
        ")",sep="") 
)) 

} 

(LinearRateMPG<-MyLinearRateFunctions('mpg')) 

# function(a,b,mpg) 1/(a + b*mpg) 
# <environment: 0x11c2f2a00> 

(LinearRateCYL<-MyLinearRateFunctions('cyl')) 

# function(a,b,cyl) 1/(a + b*cyl) 
# <environment: 0x11e4cb908> 

(LinearRateDISP<-MyLinearRateFunctions('disp')) 

# function(a,b,disp) 1/(a + b*disp) 
# <environment: 0x11e47eae8> 

答えて

1

がありそこに着くために、より簡潔な方法であるが、ここでは1な考え方は次のとおりです。fn()の最初の行で

fn <- function(x) { 
    f <- eval(bquote(function(a, b) 1/(a + b * .(as.name(x))))) 
    formals(f) <- c(formals(f), setNames(alist(dummy =), x)) 
    f 
} 

、私たちは、数学の式にxを置換するbquote()を使用しています。呼び出しから関数に変換するには、それを評価する必要があります(eval())。次に、2行目で、3番目の引数を仮引数リストに追加します。最後の行は関数を返します。

fn("mpg") 
# function (a, b, mpg) 
# 1/(a + b * mpg) 
# <environment: 0x4f05c78> 

fn("cyl") 
# function (a, b, cyl) 
# 1/(a + b * cyl) 
# <environment: 0x4f9ba28> 

クイックチェック:

fn("mpg")(1, 2, 3) 
# [1] 0.1428571 
1/(1 + 2 * 3) 
# [1] 0.1428571 

そしてeval(parse(text = ...))へのより良い代替手段を求めてくれてありがとう、それは間違いなく悪い習慣です。

+0

機能環境は、 'evalの()'に変更することができます。 –

1

pryr::make_functionを使用する代替方法があります。これは、「機能の工場」の呼び出し元の環境に機能「環境」を設定する追加の利点は、それがevalへの呼び出しを避けるように、これは見えますが、それは単にmake_function

1
の中に隠され

fn2 <- function(x) { 
    fbody <- bquote(1/(a + b * .(as.name(x)))) 
    fargs <- setNames(alist(,,),c('a','b',x)) 
    pryr::make_function(fargs,fbody, env=parent.frame(2)) 
} 

を呼び出しています

これはベースRのみを使用し、evalは使用しません。最初にテンプレートとして使用する関数を設定してから、書式を変更し、本文を設定し、環境を設定します。

factory <- function(x, envir = parent.frame()) { 
    fun <- function(a, b, x) {} 
    names(formals(fun))[[3]] <- x 
    body(fun) <- substitute(1/(a+b*x), list(x = as.name(x))) 
    environment(fun) <- envir 
    fun 
} 

# test 
myfun <- factory("m") 

寄付:必要に応じて

> myfun 
function (a, b, m) 
1/(a + b * m) 
関連する問題