मैं किसी अन्य पैकेज में परिभाषित जेनेरिक के लिए एक एस 3 विधि बना रहा हूं। जेनेरिक के लिए एक पुरानी विधि कुछ कंसोल आउटपुट उत्पन्न करती है जो फ़ंक्शन रिटर्न वैल्यू के हिस्से के रूप में वापस नहीं आती है, यह केवल कंसोल पर मुद्रित होती है। मैं उस आउटपुट को अपनी विधि में उपयोग के लिए कैप्चर करना चाहता हूं।

मैंने NextMethod() पर capture.output() का उपयोग करने की कोशिश की, लेकिन इसका परिणाम एक विचित्र त्रुटि है:

foo <- function(x, ...) UseMethod("foo")
foo.bar <- function(x, ...) cat(x, "\n")
foo.baz <- function(x, ...) capture.output(NextMethod())

foo(structure(1, class = "bar"))
#> 1
foo(structure(1, class = c("baz", "bar")))
#> Error: 'function' is not a function, but of type 8

क्या यह अपेक्षित व्यवहार, एक ज्ञात सीमा या एक बग है? मुझे त्वरित खोज के साथ इस त्रुटि से मेल खाने वाली कोई चीज़ नहीं मिली। मैं अगले S3 विधि के आउटपुट को किसी अन्य S3 विधि में कैसे कैप्चर कर सकता हूं?

0
Mikko Marttila 28 सितंबर 2018, 16:33

2 जवाब

सबसे बढ़िया उत्तर

यह है... "अपेक्षित व्यवहार।" मैं ऐसा इसलिए कह रहा हूं क्योंकि मेरा मानना ​​है कि यह तकनीकी रूप से सच है, लेकिन उपयोगकर्ता के लिए यह आवश्यक रूप से अपेक्षित करने का कोई तरीका नहीं है। यदि आपको परवाह नहीं है कि ऐसा क्यों होता है, लेकिन केवल यह देखना चाहते हैं कि इसके आसपास कैसे काम किया जाए, तो "द फिक्स" शीर्षक पर जाएं, क्योंकि त्रुटि की निम्नलिखित व्याख्या थोड़ी शामिल है।

'function' is not a function, but of type 8 का क्या मतलब है?

type 8 एक प्रकार 8 SEXP को संदर्भित करता है। आर इंटर्नल मैनुअल के एक सेक्शन से ए>:

R उपयोगकर्ता जिसे चर या ऑब्जेक्ट समझते हैं, वे प्रतीक हैं जो एक मान से बंधे होते हैं। मान को या तो एक SEXP (एक सूचक) के रूप में माना जा सकता है, या वह संरचना जिसे वह इंगित करता है, एक SEXPREC...

वर्तमान में SEXPTYPEs 0:10 और 13:25 उपयोग में हैं....

कोई SEXPTYPE विवरण नहीं
...
3 CLOSXP बंद
...
8 BUILTINSXP बिलिन फ़ंक्शन

NextMethod() CLOSXP की अपेक्षा करता है, BUILTINSXP की नहीं। अगर हम स्रोत कोड< को देखें तो हम इसे देख सकते हैं। /a> (पंक्ति 717 के आसपास) do_nextmethod() का, C फ़ंक्शन अंतर्निहित NextMethod()

SEXP attribute_hidden do_nextmethod(SEXP call, SEXP op, SEXP args, SEXP env)
{
    // Some code omitted
    if (TYPEOF(s) != CLOSXP){ /* R_LookupMethod looked for a function */
        if (s == R_UnboundValue)
            error(_("no calling generic was found: was a method called directly?"));
        else
            errorcall(R_NilValue,
              _("'function' is not a function, but of type %d"),
              TYPEOF(s));
    }

तो यहाँ ऐसा क्यों हुआ? यहीं पर वो मुश्किल हो जाता है। मेरा मानना ​​​​है कि ऐसा इसलिए है क्योंकि NextMethod() से capture.output() पास करके, इसे eval() का उपयोग करके कॉल किया जाता है, जो एक अंतर्निहित है (देखें builtins())।

तो हम इससे कैसे निपट सकते हैं? पढ़ते रहिये...

जोड़

हम sink(), cat(), और tempfile() के चतुर उपयोग के साथ कैप्चर आउटपुट का अनुकरण कर सकते हैं:

foo.baz <- function(x, ...) {
    # Create a temporary file to store the output
    tmp <- tempfile("tmp.txt")
    # start sink()
    sink(tmp)
    # call NextMethod() just for the purpose of capturing output
    NextMethod()
    # stop sink'ing
    sink()
    # store the output in an R object
    y <- readLines(tmp)
    # here we'll cat() the output to make sure it worked
    cat("The output was:", y, "\n")
    # destroy the temporary file
    unlink(tmp)
    # and call NextMethod for its actual execution
    NextMethod()
}

foo(structure(1, class = c("baz", "bar")))
# 1 
3
duckmayr 28 सितंबर 2018, 20:27

मुझे यकीन नहीं है कि आपने जो देखा वह प्रलेखित है या नहीं: दस्तावेज़ीकरण ?NextMethod स्पष्ट करता है कि यह एक नियमित कार्य नहीं है, लेकिन मैंने यह देखने के लिए सभी विवरणों का पालन नहीं किया कि क्या आपके उपयोग की अनुमति होगी।

आप जो चाहते हैं उसे करने का एक तरीका होगा

foo.baz <- function(x, ...) {class(x) <- class(x)[-1]; capture.output(foo(x, ...))}

यह मानता है कि विधि को कॉल से सीधे जेनेरिक में बुलाया गया था; यदि कोई तीसरा स्तर है तो यह काम नहीं करेगा, और foo.baz स्वयं NextMethod() द्वारा लागू किया गया था।

0
user2554330 28 सितंबर 2018, 18:16