2014-09-27 5 views
5

मान लीजिए मैं एक सदिश की तरह एस 4 वर्ग है:एस 4 ऑब्जेक्ट्स पर लापरवाही से काम क्यों नहीं करता है, जिसमें as.list.default विधि है?

.MyClass <- setClass("MyClass", representation(a="numeric", b="character")) 

setMethod("[", c("MyClass", "numeric", "missing"), function(x, i, j, ...) { 
    do.call(initialize, c(x, sapply(slotNames(x), function(y) slot(x, y)[i], 
      simplify=FALSE))) 
}) 

setMethod("length", "MyClass", function(x) length([email protected])) 

और कहते हैं कि मैं भी as.list और as.list.default के लिए तरीकों को परिभाषित किया है:

setGeneric("as.list") 
setMethod("as.list", "MyClass", 
      function(x) lapply(seq_along(x), function(i) x[i])) 
setGeneric("as.list.default") 
setMethod("as.list.default", "MyClass", 
      function(x) lapply(seq_along(x), function(i) x[i])) 

अब इस वर्ग की एक वस्तु को देखते हुए myobj:

myobj <- .MyClass(a=1:4, b=letters[1:4]) 

जब मैं lapply का उपयोग करता हूं, तो यह शिकायत करता है:

> lapply(myobj, function(i) rep([email protected], [email protected])) 
Error in as.list.default(X) : 
    no method for coercing this S4 class to a vector 

लेकिन अगर मैं as.list.default उपयोग करते हैं, समारोह वांछित आउटपुट देता है:

> lapply(as.list.default(myobj), function(i) rep([email protected], [email protected])) 
[[1]] 
[1] "a" 

[[2]] 
[1] "b" "b" 
... 

क्यों lapply भले ही मैं वर्ग के लिए as.list.default के लिए एक विधि को परिभाषित किया है काम नहीं करता है?

स्पष्ट रूप से मैं कक्षा के लिए lapply विधि मैन्युअल रूप से परिभाषित कर सकता हूं और यह ठीक (नीचे) काम करेगा, लेकिन मैं सोच रहा था कि वास्तव में त्रुटि का सामना करना पड़ रहा है। lapply क्यों मेरे ऑब्जेक्ट को वेक्टर में कॉन्स करने का प्रयास कर रहा है, भले ही वह जिस फ़ंक्शन को कॉल कर रहा है उसे ऑब्जेक्ट को सूची में बदलना चाहिए?

setGeneric("lapply") 
setMethod("lapply", c("MyClass", "function"), function(X, FUN, ...) { 
    lapply(as.list(X), FUN, ...) 
}) 
lapply(myobj, function(i) rep([email protected], [email protected])) 
+0

यहाँ जेनरिक को फिर से परिभाषित करने की आवश्यकता नहीं हो रहा है। अन्यथा आश्चर्यजनक है कि आपके कोड को ठीक काम करना चाहिए। – agstudy

+0

मैं आम तौर पर जेनेरिक बना देता हूं इसलिए मुझे 'जेनेरिक फंक्शन बनाना ...' संदेश नहीं दिख रहा है। मैं 'सिंक' या 'capture.output' का उपयोग कर सकता हूं, लेकिन यह जेनरिक को परिभाषित करने से भी गड़बड़ लगता है। –

उत्तर

4

?Methods मदद पृष्ठ से, एक व्यावहारिक रणनीति

#same 
.MyClass <- setClass("MyClass", representation(a="numeric", b="character")) 

setMethod("[", c("MyClass", "numeric", "missing"), function(x, i, j, ...) { 
    do.call(initialize, c(x, sapply(slotNames(x), function(y) slot(x, y)[i], 
      simplify=FALSE))) 
}) 

setMethod("length", "MyClass", function(x) length([email protected])) 

#different 
as.list.MyClass <-function(x) { 
    lapply(seq_along(x), function(i) x[i]) 
} 
setMethod("as.list", "MyClass", as.list.MyClass) 

#test 
myobj <- .MyClass(a=1:4, b=letters[1:4]) 
lapply(myobj, function(i) rep([email protected], [email protected])) 

# [[1]] 
# [1] "a" 
# 
# [[2]] 
# [1] "b" "b" 
# 
# [[3]] 
# [1] "c" "c" "c" 
# 
# [[4]] 
# [1] "d" "d" "d" "d" 
+0

यहां 'setMethod' का उपयोग करने की आवश्यकता नहीं है। जेनेरिक एस 3 विधि as.list का उपयोग करके आप बस अपने एस 4 ऑब्जेक्ट को मजबूर करते हैं। – agstudy

+3

@agstudy तो क्या मैंने 'विधि' सहायता पृष्ठ की गलत व्याख्या की? या यह गलत है? (मैं मानता हूं कि काम करने के लिए 'लापरवाही' प्राप्त करने की आवश्यकता नहीं है, लेकिन ऐसा लगता है कि यह सिर्फ एक सर्वोत्तम अभ्यास है।) – MrFlick

+1

ईमानदारी से मैंने मदद नहीं पढ़ी। लेकिन एस 3 फ़ंक्शन को जबरन (रखरखाव कारण) के लिए S4 विधि के रूप में उपयोग करना एक अच्छा अभ्यास है। सिर्फ यह दिखाने के लिए मेरी टिप्पणी है कि आप सख्ती से एस 4 तरीके से सवाल का जवाब नहीं देते हैं, यह अच्छा कामकाज है। – agstudy

संबंधित मुद्दे