r आर में उच्च स्तर के कार्य-क्या कोई आधिकारिक रचना ऑपरेटर या करी फ़ंक्शन है?




functional-programming higher-order-functions (4)

ये दोनों फ़ंक्शन वास्तव में पीटर डैनबर्ग (जो मूल रूप से आर-हेल्प पर बायरन एलिस के समाधान पर आधारित थे) से roxygen पैकेज ( यहां स्रोत कोड देखें ) में मौजूद हैं:

Curry <- function(FUN,...) {
  .orig = list(...);
  function(...) do.call(FUN,c(.orig,list(...)))
}

Compose <- function(...) {
  fs <- list(...)
  function(...) Reduce(function(x, f) f(x),
                       fs,
                       ...)
}

आर। फ़ंक्शन के उपयोग पर ध्यान दें, जो आर। See में कार्यात्मक प्रोग्रामिंग करने की कोशिश करते समय बहुत मददगार हो सकता है। अधिक विवरणों के लिए कम करें (जो कि Map और Filter जैसे अन्य कार्यों को भी कवर करता है)।

और करी का आपका उदाहरण (इस उपयोग में थोड़ा अलग):

> library(roxygen)
> p <- Curry(paste, collapse="")
> p(letters[1:10])
[1] "abcdefghij"

कम्पोज़ की उपयोगिता दिखाने के लिए यहां एक उदाहरण दिया गया है (पत्रों के लिए तीन अलग-अलग कार्यों को लागू करना):

> Compose(function(x) x[length(x):1], Curry(paste, collapse=""), toupper)(letters)
[1] "ZYXWVUTSRQPONMLKJIHGFEDCBA"

और आपका अंतिम उदाहरण इस तरह काम करेगा:

> aggregate(df[,"t"], df["l"], Compose(Curry(paste, collapse=""), toupper))
  l    x
1 1  ABG
2 2 DEFH
3 3  CIJ

अंत में, यहाँ plyr साथ एक ही काम करने का एक तरीका है (पहले से दिखाए गए aggregate आसानी by या aggregate भी किया जा सकता है):

> library(plyr)
> ddply(df, .(l), function(df) paste(toupper(df[,"t"]), collapse=""))
  l   V1
1 1  ABG
2 2 DEFH
3 3  CIJ

मैं R में कंपोज़ ऑपरेटर बना सकता हूं:

 `%c%` = function(x,y)function(...)x(y(...)) 

इस तरह इस्तेमाल किया जाना है:

 > numericNull = is.null %c% numeric
 > numericNull(myVec)
 [2] TRUE FALSE

लेकिन मैं यह जानना चाहूंगा कि क्या इस तरह के काम करने के लिए कार्यों का एक आधिकारिक सेट है और अन्य संचालन जैसे कि आर। में करी करना। यह मेरे कोड में कोष्ठक, फ़ंक्शन कीवर्ड आदि की संख्या को कम करना है।

मेरी करी समारोह:

> curry=function(...){
    z1=z0=substitute(...);z1[1]=call("list");
    function(...){do.call(as.character(z0[[1]]),
                          as.list(c(eval(z1),list(...))))}}
> p = curry(paste(collapse=""))
> p(letters[1:10])
[1] "abcdefghij"

यह विशेष रूप से उदाहरण के लिए अच्छा है:

> df = data.frame(l=sample(1:3,10,rep=TRUE), t=letters[1:10])
> aggregate(df$t,df["l"],curry(paste(collapse="")) %c% toupper)
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ

जो मुझे बहुत अधिक सुंदर और संपादन योग्य लगता है:

> aggregate(df$t, df["l"], function(x)paste(collapse="",toupper(x)))
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ

मूल रूप से मैं जानना चाहता हूं - क्या यह पहले से ही आर के लिए किया गया है?


यदि आप चाहते हैं कि चर के 'नाम' सही तरीके से गुजरें तो अधिक जटिल दृष्टिकोण की आवश्यकता होती है।

उदाहरण के लिए, यदि आप plot(rnorm(1000),rnorm(1000)) तो आपको अपने x- और y- अक्षों पर अच्छे लेबल मिलेंगे। इसका एक और उदाहरण data.frame

> data.frame( rnorm(5), rnorm(5), first=rpois(5,1), second=rbinom(5,1,0.5) )
    rnorm.5. rnorm.5..1 first second
1  0.1964190 -0.2949770     0      0
2  0.4750665  0.8849750     1      0
3 -0.7829424  0.4174636     2      0
4  1.6551403  1.3547863     0      1
5  1.4044107 -0.4216046     0      0

ऐसा नहीं है कि डेटा.फ्रेम ने कॉलमों को उपयोगी नाम दिए हैं।

करी के कुछ कार्यान्वयन ठीक से ऐसा नहीं कर सकते हैं, जिससे अपठनीय स्तंभ नाम और प्लॉट लेबल हो सकते हैं। इसके बजाय, मैं अब कुछ इस तरह का उपयोग करें:

Curry <- function(FUN, ...) {
    .orig = match.call()
    .orig[[1]] <- NULL # Remove first item, which matches Curry
    .orig[[1]] <- NULL # Remove another item, which matches FUN
    function(...) {
        .inner = match.call()
        .inner[[1]] <- NULL # Remove first item, which matches Curry
        do.call(FUN, c(.orig, .inner), envir=parent.frame())
    }
}

यह काफी जटिल है, लेकिन मुझे लगता है कि यह सही है। match.call सभी match.call को पकड़ लेगा, पूरी तरह से याद match.call कि किन शब्दों ने match.call को परिभाषित किया (यह अच्छे लेबल के लिए आवश्यक है)। समस्या यह है कि यह बहुत सारे args पकड़ता है - न केवल ... बल्कि FUN भी। यह उस फ़ंक्शन का नाम भी याद रखता है जिसे कॉल किया जा रहा है ( Curry )।

इसलिए, हम इन पहली दो प्रविष्टियों को .orig में हटाना चाहते हैं ताकि .orig वास्तव में सिर्फ ... तर्कों से मेल खाती हो। इसलिए हम करते हैं .orig[[1]]<-NULL दो बार - हर बार एक प्रविष्टि को हटाता है और बाकी सब को बाईं ओर शिफ्ट करता है।

यह परिभाषा पूरी करता है और अब हम उपरोक्त के समान ही प्राप्त करने के लिए निम्न कार्य कर सकते हैं

Curry(data.frame, rnorm(5), rnorm(5) )( first=rpois(5,1) , second=rbinom(5,1,0.5) )

envir=parent.frame() पर एक अंतिम नोट। मैंने यह सुनिश्चित करने के लिए इसका उपयोग किया कि यदि आपके पास '.inner' या '.orig' नामक बाहरी चर हैं तो कोई समस्या नहीं होगी। अब, सभी चरों का मूल्यांकन उस स्थान पर किया जाता है जहाँ करी को बुलाया जाता है।



आर में कार्यात्मक प्रोग्रामिंग के लिए मानक स्थान अब functional पुस्तकालय है।

पुस्तकालय से:

कार्यात्मक: करी, रचना और अन्य उच्च-क्रम के कार्य

उदाहरण:

   library(functional)
   newfunc <- Curry(oldfunc,x=5)

CRAN: https://cran.r-project.org/web/packages/functional/index.html

पुनश्च: यह पुस्तकालय ROxigen पुस्तकालय का विकल्प है।





higher-order-functions