2017-09-08 10 views
3

私の読書であるHadley's advice on building S3 objectsに沿って、ヘルパー関数、コンストラクタ関数、およびバリデーター関数を使用しています。単純な再現例:複数の機能を持つオブジェクトの名前

test_object <- function(x, y, z) { 
    new_test_object(x, y, z) 
} 

new_test_object <- function(x, y, z) { 
    structure(list(x = x, 
        y = y, 
        z = z, 
        x_name = deparse(substitute(x))), 
       class = "test_object") 
} 

validate_test_object <- function(test_object) { 
    # Anything goes 
    test_object 
} 

Iは、渡された項目があったこと元の名前(上記の例で$x_name)で値を含むように、得られたオブジェクトを希望。

alpha = "a" 
test_constructor <- new_test_object(x = alpha, y = "b", z = "c") 
test_constructor$x_name 
# [1] "alpha" 

でもない、私はヘルパー関数を使用している場合は::

test_helper <- test_object(x = alpha, y = "b", z = "c") 
test_helper$x_name 
# [1] "x" 

私も[1] "alpha"を返すようにtest_helper$x_nameをしたいと思い、私が直接コンストラクタを呼び出す場合deparse(substitute(...))トリックは動作します。

ヘルパー段階でdeparse(substitute(...))ステップを行うためのショート、コンストラクタ関数(new_test_object())それはヘルパーを経由して来た場合、オブジェクトxの「オリジナル」の名前にアクセスする方法はありますか?ヘルパー関数がそれをコンストラクタに渡すときに、その名前がその名前を確実に通過するようにするには?ここで

答えて

4

:あなたは別の関数

test_object <- function(x, y, z) { 
    x_name = deparse(substitute(x)) 
    new_test_object(x, y, z, x_name = x_name) 
} 

new_test_object <- function(x, y, z, ...) { 
    args <- list(...) 
    if(is.null(args[["x_name"]])){ 
    structure(list(x = x, 
        y = y, 
        z = z, 
        x_name = deparse(substitute(x))), 
       class = "test_object") 
    } 
    else{ 
    structure(list(x = x, 
        y = y, 
        z = z, 
        x_name = args[["x_name"]]), 
       class = "test_object") 
    } 

} 

そしてここからそれを呼び出しているときに名前を渡す...引数を追加した結果でありますここに目的はありますか?ある関数を別の関数へのラッパーとして使用しているだけの場合は、引数を保持する方が良い方法があります。例

test_object <- function(x, y, z) { 
    call <- match.call() 
    call[[1]] <- quote(new_test_object) 
    eval(call) 
} 

のためではなく、一般的には変数の名前から情報を取得するためにdeparse()に頼ることは、非常に信頼性の高い方法ではありません。このような情報は、必要に応じて設定できる適切なパラメータである方がよいでしょう。これにより、関数の柔軟性が大幅に向上します。

test_object <- function(x, y, z, xname=deparse(substitute(x))) { 
    new_test_object(x, y, z, xname=xname) 
} 

new_test_object <- function(x, y, z, xname=deparse(substitute(x))) { 
    structure(list(x = x, 
        y = y, 
        z = z, 
        x_name = xname), 
       class = "test_object") 
} 
+0

「本当にここの目的は何ですか?」という正直な答え:ハドレーがそう言ったからです!彼の論理は、ヘルパーが "他の人がこのクラスのオブジェクトを構築して検証する(作成する)ための、便利できちんとパラメータ化された方法を提供する"ということです。私はあなたの提案や適切なパラメータ設定が好きです。きちんとしているように見えます。ありがとう! – jamse

0

は美しいではない修正です:

本当に何
test_helper <- test_object(x = alpha, y = "b", z = "c") 
test_helper$x_name 
# [1] "alpha" 
関連する問題