我們可以在參數(shù)列表中加上一個(gè)省略號(hào)(...)來(lái)方便地指定任意長(zhǎng)度的參數(shù)。
下面通過(guò)構(gòu)造一個(gè)函數(shù)來(lái)舉例說(shuō)明。這個(gè)函數(shù)的功能是打印出第一個(gè)參數(shù)的內(nèi)容,然后將剩下的所有參數(shù)傳遞給summary函數(shù)。
首先構(gòu)造一個(gè)函數(shù),它有一個(gè)參數(shù)x。這個(gè)函數(shù)的參數(shù)列表中還包含了一個(gè)省略號(hào),因此這個(gè)省略號(hào)將成為我們調(diào)用的summary函數(shù)的參數(shù)。
> v <- c(sqrt(1:100))
> f <- function(x, ...) { print(x); summary(...)}
> f("Here is the summary for v.", v, digits=2)
[1] "Here is the summary for v."
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.0 5.1 7.1 6.7 8.7 10.0
我們可以發(fā)現(xiàn),x之后的所有參數(shù)都被傳進(jìn)了summary函數(shù)。
有時(shí)候我們想要知道這些可變參數(shù)列表的所有參數(shù)值,這時(shí)候我們需要做的是在函數(shù)內(nèi)部將對(duì)象...轉(zhuǎn)換為一個(gè)列表。
舉個(gè)例子,我們構(gòu)造一個(gè)函數(shù)然后對(duì)所有的參數(shù)進(jìn)行相加求和。
> addemup <- function(x, ...){
+ args <- list(...)
+ for (a in args) x <- x + a
+ x
+ }
> addemup(1,1)
[1] 2
> addemup(1,2,3,4,5)
[1] 15
我們還可以通過(guò)..1,..2到..9等直接引用列表...中的內(nèi)容。..1表示第一項(xiàng),..2表示第二項(xiàng),以此類推。這有點(diǎn)類似于shell中通過(guò)$引用相應(yīng)的參數(shù)。看來(lái)很多的編程語(yǔ)言都存有相同的參數(shù)傳遞機(jī)制。
函數(shù)的屬性
R中包含了一系列的函數(shù)用于提取函數(shù)類型對(duì)象的信息。
args函數(shù)可以用來(lái)查看函數(shù)包含了哪些參數(shù),args返回一個(gè)函數(shù)類型的對(duì)象,函數(shù)體為NULL。
> args(sin)
function (x)
NULL
> args('?')
function (e1, e2)
NULL
> args(args)
function (name)
NULL
> args(lm)
function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...)
NULL
如果我們想要在R代碼中對(duì)函數(shù)的參數(shù)列表進(jìn)行操作,formals函數(shù)是一個(gè)很好的工具,它會(huì)返回一個(gè)配對(duì)列表對(duì)象(對(duì)應(yīng)參數(shù)名和設(shè)定的默認(rèn)參數(shù)值)。
注意,formals函數(shù)僅能運(yùn)行在R寫的函數(shù)上(類型為closure的對(duì)象),而不能在內(nèi)嵌函數(shù)(bulti-in function)上運(yùn)行。(可能是因?yàn)閮?nèi)嵌函數(shù)是C寫的吧)
> f <- function(x, y=1, z=2) {x+y+z}
> f.formals <- formals(f)
> f.formals
$x
$y
[1] 1
$z
[1] 2
我們還可以利用它來(lái)更改函數(shù)的形參。例如:
> f.formals$y <- 3
> formals(f) <- f.formals
> args(f)
function (x, y = 3, z = 2)
NULL
R提供了一個(gè)非常方便的函數(shù)alist用來(lái)構(gòu)建參數(shù)列表。我們可以像定義函數(shù)一樣很簡(jiǎn)單地指定參數(shù)列表。(注意,如果參數(shù)沒(méi)有默認(rèn)值,我們不必給它指定一個(gè)值,但是必須包含等號(hào)。)
> f <- function(x, y=1, z=2) { x + y + z}
> formals(f) <- alist(x=, y=100, z=200)
> args(f)
function (x, y = 100, z = 200)
NULL
R提供了與formals函數(shù)類似的函數(shù)body來(lái)返回函數(shù)的函數(shù)體:
> body(f)
{
x + y + z
}
我們也可以將它放在賦值語(yǔ)句的左邊,通過(guò)賦值操作來(lái)改變函數(shù)體。
> f
function (x, y = 100, z = 200)
{
x + y + z
}
> body(f) <- expression({x * y * z})
> f
function (x, y = 100, z = 200)
{
x * y * z
}
注意,函數(shù)體的類型為expression,所以重新賦值時(shí),也必須為expression類型。
改變其他環(huán)境
這里介紹<<-操作符的使用:比如var <<- value,它會(huì)使解釋器首先在當(dāng)前環(huán)境中檢索尋找符號(hào)var。如果解釋器無(wú)法在當(dāng)前環(huán)境中找到符號(hào)var,那么接下來(lái)會(huì)在父環(huán)境中繼續(xù)尋找。解釋器將這樣遞歸地在各個(gè)環(huán)境中尋找直到找到該符號(hào)或到達(dá)全局環(huán)境。加入解釋器在到達(dá)全局環(huán)境時(shí)依然沒(méi)有找到var,那么R會(huì)在全局環(huán)境中指定var的值為value。
下面是一個(gè)例子:
> x
錯(cuò)誤: 找不到對(duì)象'x'
> doesnt.assign.x <- function(i){ x <- i}
> doesnt.assign.x(4)
> x
錯(cuò)誤: 找不到對(duì)象'x'
> assign.x <- function(i){ x <<- i}
> assign.x(4)
> x
[1] 4
學(xué)習(xí)整理自《R核心技術(shù)手冊(cè)》
