寫好function一點都不簡單,這邊分享和整理在撰寫function要思考的事情。而這邊主要是講R語言裡的function,但其實很多觀念是可以供通的,可以分別為:一個function的組成、什麼是好的function、各種function的類型、何時要寫function、撰寫function的流程。
function是一連串expression包裝(encapsulate)起來而成,expression的多寡決定一個function可以處理事情的多寡,恰當好處的功能,是一個好function的關鍵,能解決問題的function就是有用的,而function裡面細節的設計則決定會不會讓使用者愛用。
首先,理解在R裡面,一個 function基本由什麼組成:
- 參數arguments:
- 可以使用formals()檢視
- 主體的代碼body:
- 可以使用body()檢視
- 函數中使用變數對應的“變數空間”environment:
- 可以使用environment()檢視
再來理解,怎麼樣是一個好的function:
- 能解決當下問題(最重要)
- 易讀性
- 輸入輸出高穩定性(stable / pure function )
- 對於錯誤訊息的處理(error handling)
- 減少對於hidden argument的依賴(比如環境變數等等)
特殊的Function:
- infix function:(或可以稱為binary operator)
- 函數出現在兩個參數之間,像是
%%
,%*%
,%/%
,%in%
,%o%
,%x%
. - 可以這樣來定義:
- 函數出現在兩個參數之間,像是
[ code language="r" ]
%g%
paste(left, right)
}
[/code ]
- replacement function
- 函數只接改變其參數的數值。
- pure function
- 沒有side effect,輸入跟輸入乾淨
- function with side effect
- 會直接改變環境中的設定
library()、
setwd()、
Sys.setenv()
、Sys.setlocale()
、plot()、
write()、
write.csv()
、saveRDS()、
options()
、par()
- 會直接改變環境中的設定
何時是寫function的好時機呢?
這邊可以參考這本Executive Data Science 裡面的說法,當你開始寫一個code來完成一件事情的時候,這時候就要仔細記錄使用場景,要第二次用這個代碼來完成事情的時候,便可以考慮一下撰寫function,當第三次依舊需要再做一樣的事情時,就可以規劃來把function包成packages。
撰寫function的基本流程
- 先定義好自己function要完成的事情
- 先用一連串的expression來做快速的prototype
- 將其包裝成function
- 進行重構(refactoring),盡量讓代碼完成最小單位的事情,過多的複雜會使代碼難以閱讀和管理
- 進行vectorize,盡量讓函數的輸入維持成單個數入,避免過度的使function的表現更好預測
- 設定default值