2012-08-06 208 views
4

我有一種情況,我想通過Compose鏈接的函數傳遞參數。我意識到我可以在參數中使用庫裏,但是我希望得到的函數比這更靈活。這裏有一個簡單的測試用例來說明問題:將參數傳遞給Compose的函數?

> library(functional) 
> f <- function(x, scale) x^2*scale 
> g <- function(y, shift) sqrt(y)+shift 
> h <- Compose(f,g) 
> h(1) 
Error in x^2 * scale : 'scale' is missing 
> h(1, scale=1, shift=0) 
Error in Reduce(function(x, f) f(x), fs, ...) : 
    unused argument(s) (scale = 1, shift = 0) 

有沒有辦法使用Compose使得它允許產生的功能仍然允許參數被調用時? ?Compose不是很有幫助,除了可能作爲一個可愛的鍵盤elegy。

+0

您從哪些包獲得撰寫? – Dason 2012-08-06 13:53:36

+0

安德烈 - 苛刻! @Dason這是(現在,感謝喬希的編輯)我的代碼中的第一行:-)。對不起,忘了複製/粘貼該行。 – 2012-08-06 13:58:06

回答

6

由於function composition是在計算機科學中制定的,所有的功能都只有一個參數。 Composition函數也假設這一點。這是一個典型的解決方案。另一個複雜因素是任何其他命名參數都必須傳遞給組合過程中的正確函數。

這裏有幾個辦法:

h1 <- function(scale, shift) 
    Compose(Curry(f,scale), Curry(g,shift)) 

h1採取命名參數,並創建與那些在正確的令行禁止組成的功能。返回是1參數功能:

> h1(scale=1, shift=0)(1) 
[1] 1 

另一種方法是延遲壓縮(並因此延遲)直到實際功能評估。在這種情況下,原始的「撰寫」功能只是設置一切,但實際上並不構成,返回一個函數,該函數可以進行粘貼,合成和評估。

ComposeDelayedCurry <- function(...) { 
    fs <- list(...) 
    all.formals <- lapply(fs, formals) 
    function(...) { 
    local.args <- list(...) 
    pos.args <- lapply(all.formals, function(f) { 
     local.args[names(f)[[-1]]] 
    }) 
    curried <- lapply(seq_along(fs), function(i) { 
     do.call(Curry, c(fs[[i]], pos.args[[i]])) 
    }) 
    do.call(Compose, curried)(..1) 
    } 
} 

h2 <- ComposeDelayedCurry(f,g) 

現在呼籲h2將在評估時做所有的工作。這做了幾個假設。一個是每個函數(和函數調用)的第一個參數是正在編寫的函數。第二個是所有其他參數都是命名參數。沒有任何東西可以通過...傳遞給函數。這是因爲必須檢查每個函數的形式,以便知道每個參數「去」的位置。我認爲這將處理不指定具有默認值的參數,但我不完全確定。

> h2(1, scale=1, shift=0) 
[1] 1 
> h2(3, scale=5, shift=2) 
[1] 8.708204 
> sqrt(5*(3^2))+2 
[1] 8.708204