وظائف المستوى الأعلى في R - هل هناك مشغل يؤلف رسميا أو وظيفة كاري؟

StackOverflow https://stackoverflow.com/questions/2228544

سؤال

يمكنني إنشاء مشغل يؤلف في R:

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

لاستخدامها مثل هذا:

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

ولكن أود أن أعرف ما إذا كان هناك مجموعة رسمية من الوظائف للقيام بهذا النوع من الأشياء وغيرها من العمليات مثل الكهرج في R. هذا إلى حد كبير للحد من عدد الأقواس، والكلمات الرئيسية الوظيفية وغيرها في التعليمات البرمجية.

وظيفة الكاري الخاصة بي:

> 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

أساسا أريد أن أعرف - هل تم ذلك بالفعل ل R؟

هل كانت مفيدة؟

المحلول

المكان القياسي للبرمجة الوظيفية في R هو الآن functional مكتبة.

من المكتبة:

وظيفية: الكاري، وتأليف، وغيرها من وظائف الدرجة العليا

مثال:

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

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

PS: هذه المكتبة بديل ROxigen مكتبة.

نصائح أخرى

كل من هذه الوظائف موجودة بالفعل في ال roxygen صفقة (انظر شفرة المصدر هنا) من بيتر دانينبرغ (كان أساسا أساسا حل Byron Ellis على R-Help):

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

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

لاحظ استخدام Reduce وظيفة، والتي يمكن أن تكون مفيدة للغاية عند محاولة القيام برمجة وظيفية في R. انظر؟ تقلل لمزيد من التفاصيل (والتي تغطي أيضا وظائف أخرى مثل Map و Filter).

ومثالك على الكاري (مختلفة قليلا في هذا الاستخدام):

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

إليك مثال لإظهار فائدة Compose (تطبيق ثلاث وظائف مختلفة على الحروف):

> 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 (يمكن أيضا القيام به بسهولة 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

هناك وظيفة تسمى الكاري في روكسجين صفقة.
وجدت عبر هذه المحادثة على أرشيف البريد الإلكتروني.

مطلوب نهج أكثر تعقيدا إذا كنت تريد "أسماء" المتغيرات لتمرير بدقة.

على سبيل المثال، إذا قمت بذلك 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

ليس أن Data.Frame قد عين أسماء مفيدة للأعمدة.

قد لا تفعل بعض تطبيقات الكاري هذا بشكل صحيح، مما يؤدي إلى أسماء الأعمدة غير القابلة للقراءة وتسميات المؤامرة. بدلا من ذلك، أنا الآن استخدم شيئا مثل هذا:

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 سيتم التقاط جميع Args، وتذكر تماما ما التعبيرات التي حددت Args (هذا ضروري للملصقات اللطيفة). المشكلة هي أنه يمسك الكثير من 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". الآن، يتم تقييم جميع المتغيرات في المكان الذي يطلق عليه الكاري.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top