अवक्षेपण का तेज़ विकल्प ()


9

मैं एक पैकेज बनाए रखता हूं जो बार-बार कॉल करने पर निर्भर करता है deparse(control = c("keepNA", "keepInteger"))controlहमेशा समान होता है, और अभिव्यक्ति भिन्न होती है। deparse()लगता है कि विकल्पों के एक ही सेट की बार-बार व्याख्या करने में बहुत समय व्यतीत होता है .deparseOpts()

microbenchmark::microbenchmark(
    a = deparse(identity, control = c("keepNA", "keepInteger")),
    b = .deparseOpts(c("keepNA", "keepInteger"))
)
# Unit: microseconds
# expr min  lq  mean median  uq  max neval
#    a 7.2 7.4 8.020    7.5 7.6 55.1   100
#    b 3.0 3.2 3.387    3.4 3.5  6.0   100

कुछ प्रणालियों पर, निरर्थक .deparseOpts()कॉल वास्तव में deparse()( लौ का ग्राफ ) के रनटाइम के बहुमत को ले जाते हैं ।

मैं वास्तव में सिर्फ .deparseOpts()एक बार कॉल करना चाहूंगा और फिर संख्यात्मक कोड को आपूर्ति करूंगा deparse(), लेकिन यह .Internal()सी फोन को सीधे कॉल या इनवॉइस किए बिना असंभव प्रतीत होता है , जिनमें से कोई भी पैकेज विकास के नजरिए से इष्टतम नहीं है।

deparse
# function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
#     c("call", "expression", "(", "function"), 
#     control = c("keepNA", "keepInteger", "niceNames", 
#         "showAttributes"), nlines = -1L) 
# .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control), 
#     nlines))
# <bytecode: 0x0000000006ac27b8>
# <environment: namespace:base>

क्या कोई सुविधाजनक समाधान है?

जवाबों:


4

1) एक ऐसे फंक्शन को परिभाषित करें जो कि प्रतिरूप की एक प्रति उत्पन्न करता है जिसके पर्यावरण को .deparseOpts के एक परिवर्तित संस्करण को खोजने के लिए रीसेट किया गया है जिसे पहचान फ़ंक्शन के बराबर सेट किया गया है। में Runहम तो उस समारोह एक बनाने के लिए चलाने deparse2और उस पर अमल। यह .Internalसीधे चलने से बचता है ।

make_deparse <- function() {
  .deparseOpts <- identity
  environment(deparse) <- environment()
  deparse
}

Run <- function() {
  deparse2 <- make_deparse()
  deparse2(identity, control = 65)
}

# test
Run()

2) ऐसा करने का एक और तरीका यह है कि एक कंस्ट्रक्टर फ़ंक्शन को परिभाषित किया जाए जो एक वातावरण बनाता है जिसमें एक संशोधित deparseकॉपी डालनी .deparseOptsहै और पहचान फ़ंक्शन के रूप में उस प्रतिलिपि को पुनर्परिभाषित करने के लिए एक ट्रेस जोड़ना है । फिर उस माहौल को वापस करें। हमारे पास कुछ फ़ंक्शन हैं जो इसका उपयोग करता है और इस उदाहरण के लिए हम Runइसे प्रदर्शित करने के लिए एक फ़ंक्शन बनाते हैं और फिर बस निष्पादित करते हैं Run। यह उपयोग करने से बचा जाता है.Internal

make_deparse_env <- function() {
  e <- environment()
  deparse <- deparse
  suppressMessages(
    trace("deparse", quote(.deparseOpts <- identity), print = FALSE, where = e)
  )
  e
}

Run <- function() {
  e <- make_deparse_env()
  e$deparse(identity, control = 65)
}

# test
Run()

3) एक तीसरा दृष्टिकोण deparseएक नया तर्क जोड़कर पुनर्परिभाषित .deparseOptsकरना है जो डिफ़ॉल्ट के लिए identityसेट है और control65 का डिफ़ॉल्ट होना निर्धारित करता है।

make_deparse65 <- function() {
  deparse2 <- function (expr, width.cutoff = 60L, backtick = mode(expr) %in% 
    c("call", "expression", "(", "function"), 
    control = 65, nlines = -1L, .deparseOpts = identity) {}
  body(deparse2) <- body(deparse)
  deparse2
}

Run <- function() {
  deparse65 <- make_deparse65()
  deparse65(identity)
}

# test
Run()

वाह, यह बहुत चालाक है !!! मैं ऐसा कभी सोच नहीं सकता था! वास्तव में मेरे सभी सिस्टम पर बेंचमार्किंग के लिए तत्पर हैं!
Landau

जब मैं (1) लागू करता हूं और backtickतर्क प्रस्तुत करता हूं, तो डिपार्सिंग 6 गुना तेज है! मैं उसके साथ जा रहा हूं। वर्कअराउंड के लिए बहुत बहुत धन्यवाद!
Landau

हम्म ..., जाहिर है, (1) द्वारा उत्पादित कार्यों में कॉल का R CMD checkपता लगाता है .Internal()। आसपास काम करना बहुत आसान है, मुझे बस जरूरत है make_deparse()(expr, control = 64, backtick = TRUE)। यह मूर्खतापूर्ण है कि मैं इसका उपयोग करने वाले हर बार पुनर्विक्रेता को फिर से संगठित करूं, लेकिन यह अभी भी बहुत तेज है जितना deparse()मैं पहले इस्तेमाल कर रहा था।
लैंडू

मेरे लिए नहीं। मैंने (1) में make_deparseऔर Runकार्यों के साथ एक पैकेज बनाने की कोशिश की और भाग गया R CMD buildऔर इसके R CMD check --as-cranतहत "R version 3.6.1 Patched (2019-11-18 r77437)"और यह शिकायत नहीं की और मुझे किसी भी वर्कआर्ड की आवश्यकता नहीं थी। क्या आप सुनिश्चित हैं कि आप कुछ अलग नहीं कर रहे हैं या इसके अतिरिक्त यह कारण है?
जी। ग्रोथेंडिक 15

1
यह आपके कोड द्वारा इसे शीर्ष स्तर पर परिभाषित करने के कारण हुआ था direct_deparse <- make_direct_deparse():। उत्तर में दिखाया गया कोड ऐसा नहीं करने के लिए सावधान था और केवल इसे एक फ़ंक्शन के भीतर, यानी भीतर परिभाषित किया था Run
जी। ग्रोथेंडिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.