1. 程式人生 > >(R語言)編寫自己的函式

(R語言)編寫自己的函式

10.1 函式的定義

> name <- function(arg_1, arg_2, ...) expression
expression是一個R表示式(通常是表示式語句組),並使用引數arg_i來計算出一個數值,表示式的值就是函式的返回值。
函式呼叫的形式通常都是name(expr1,expr2,...)

10.2 定義新的二元操作符

可以將函式定義為新的二元操作符:
>"%!%" <- function(X, y) { ... }
正如矩陣乘法運算子,%*%,和矩陣外積運算子%o%

10.3 指定引數和預設值

如果被呼叫函式的引數按照"name = obj"的形式給出,那麼引數的次序可以是任意的。
而且,引數序列可以在開始依次序給出,而將指定名稱的引數置於後面。
因此,如果由一個函式fun1被定義為
> fun1 <- function(data, data.frame, graph, limit) {
[function body omitted]
}
那麼函式可以有多種等價的使用方法,例如
> ans <- fun1(d, df, TRUE, 20)
> ans <- fun1(d, df, graph=TRUE, limit=20)
> ans <- fun1(data=d, limit=20, graph=TRUE, data.frame=df)
預設值 :

在很多情況下,引數都會被賦予一個普遍適用的預設值。
> fun1 <- function(data, data.frame, graph=TRUE, limit=20) { ... }
則函式可以這樣被呼叫
> ans <- fun1(d, df)
此時與上面三種情況等價,也可以這樣呼叫
> ans <- fun1(d, df, limit=10)
此時改變了一個預設值。
NOTE:引數可以是任意表達式,甚至可以是包含其他引數的表示式;

10.4 額外引數“...”

當需要將一個函式的引數傳遞給另一個函式時,可以通過包含一個額外的引數"..."實現。
fun1 <- function(data, data.frame, graph=TRUE, limit=20, ...) {
[omitted statements]
if (graph)
par(pch="*", ...)
[more omissions]
}

10.5 全域性變數和區域性變數

函式內的賦值都是區域性變數,退出函式就丟失了。
如果要在函式內進行永久賦值(定義全域性變數),需要用到“超賦值”操作符, <<-或者函式assign()。

10.6 一些高階示例

區組設計的效率因子 (E±ciency factors)
刪除列印陣列中的所有名稱
遞迴的數值積分

10.7 範疇(Scope)

函式主體內出現的標識(symbol)可以被分為3類;正式引數、區域性變數和自由變數。
正式引數就是出現在函式引數列表中的引數,他們的值由實際的函式引數與正式引數的繫結(binding)過程決定。
區域性變數是在引數主體中,由表示式求值過程決定的變數。
自由變數

為既不是正式引數又不是區域性變數的變數。賦值之後自由變數成為區域性變數。

在R中,自由變數的值由函式被建立的環境中與其同名的第一個變數值決定(我理解為最近的同名變數),這種方式被稱為詞彙式範疇(lexical scope)。
而在S中,該值由同名的全域性變數決定。
例如下面的函式cube,在R中cube(2)=8,在S中報錯為sq()找不到n。
cube <- function(n) {
sq <- function() n*n
n*sq()
}

一個銀行賬戶的例子,詳見《R語言筆記》。

10.8 定製環境

詳見《R語言筆記》。

10.9 類別,通用函式和物件定位

一個物件的類別(class)決定了他會如何被通用函式(generic function)處理。
如果引數本身沒有任何類別屬性,或者其類別在特定問題中並不滿足通用函式的要求,通常會有一個預設的動作被執行。
類別機制使使用者可以為特定的目的設計和編寫通用函式。
使用> methods(class="data.frame")可以檢視資料幀的通用函式。
使用> methods(plot)可以檢視plot函式能處理的類別。