2015-08-30 23 views
6

Aşağıdaki işlev için x değerini geçmek için magrittr kullandığımda, kullanılamaz bir işlevle sonuçlanır. Bu neden oluyor? Benim sürüm magrittr_1.5 var.Magrittr ile kapatma işleminin işlevi, işlev değerlendirmesine bir hatayla sonuçlanır

library(magrittr) 
f <- function(x) { function(y) { x + y } } 

# Case 1 (works) 
f.5 <- f(5) 
f.5(6) # returns 11 

# Case 2 (works) 
f.5 <- f(5) 
6 %>% f.5 # returns 11 

# Case 3 (fails) 
f.5 <- 5 %>% f 
6 %>% f.5 # Error in x + y (from 1) : 
      # non-numeric argument to binary operator 

# Case 4 (fails) 
f.5 <- 5 %>% f 
f.5(6); # Same error as case 3 
+3

Teknik notlar:%>% 'yardımında yararlı olabilir: * Magrittr boru operatörleri standart dışı değerlendirme kullanır. Girdilerini ele geçirdiler ve nasıl devam edeceğini anlamaya çalışırlar. Öncelikle, tüm bireysel sağ ifadelerden bir fonksiyon üretilir ve sonuç, bu fonksiyonun sol tarafa uygulanmasıyla elde edilir. Çoğu amaç için, magrittr'in değerlendirmesinin ince yönlerini göz ardı edebilir, ancak bazı işlevler çağrı ortamlarını yakalayabilir ve bu nedenle operatörleri kullanmak, boru operatörleri olmaksızın "standart arama" ile tam olarak eşdeğer olmayacaktır. * – Molx

+0

magrittr işlevleri üretmek için ('%>%' kullanımı sadece 'dplyr, rvest' ve diğer birkaç vis paketleri ile sınırlıdır), 'pipeR' boru hatları operasyonları için daha iyi bir tasarıma sahip. Örneğindeki Case3, pipeR'nin% >>% 'ile mükemmel bir şekilde çalışıyor. – Khashaa

+0

'% 5 >>% f% >>% {. (6)}' – Khashaa

cevap

2

İşte kısmi bir yanıt. Öncelikle, o

library(magrittr) 
f <- function(x) { x; function(y) x + y } 
f.5 <- 5 %>% f 
6 %>% f.5 
# [1] 11 

yanlış neler olduğunu araştırmak için, x için değerlendirmek ne görüyorsun, iç anonim fonksiyonun çağıran ortamında x değerlendirmek eğer o iş yapmak kolaydır

f <- function(x) { 
    function(y) { 
     print(sprintf("x: %s.", toString(x))) 
     x + y 
    } 
} 
## the failing case 
fails <- 5 %>% f 
6 %>% fails 
# [1] "x: function (y) \n{\n print(sprintf(\"x: %s\", toString(x)))\n x + y\n}, TRUE" 

(code) işlevi çağrıldığında, withVisible numaralı çağrıyı f numaralı telefondan aramanın sonucunu işaret ediyor. pipe fonksiyonu gövdesinde, bir çizgi, mevcuttur freduce uygun hale getirilir

body(magrittr:::pipe)[[2]][[3]][[10]] 
# env[["freduce"]] <- freduce 

(tam içerik için magrittr:::pipe bakınız). Bu hat sadece fonksiyonu freduce gerçek kod olarak değiştirilirse

(yani. magrittr:::freduce kopyalama), iş gibi görünüyor,

## Make a modified %>% operator 
mypipe <- magrittr:::pipe 

## Change that line 
body(mypipe)[[2]][[3]][[10]] <- quote(
    env[["freduce"]] <- 
     function(value, function_list) { 
      k <- length(function_list) 
      if (k == 1L) { 
       result <- withVisible(function_list[[1L]](value)) 
       if (result[["visible"]]) 
        result[["value"]] 
       else 
        invisible(result[["value"]]) 
      } else { 
       Recall(function_list[[1L]](value), function_list[-1L]) 
      } 
     } 
) 

## Redefine 
`%>%` <- mypipe() 

## Test (now it works?!) 
fails <- 5 %>% f 
6 %>% fails 
# [1] "x: 5" 
# [1] 11 

Yani, bu kısmi bir çözüm olduğu için yapamıyorum Bu şekilde freduce'un yeniden tanımlanmasının neden işe yaradığını anlamaya çalışın.