-
Notifications
You must be signed in to change notification settings - Fork 25
/
object-oriented-programming.Rmd
188 lines (126 loc) · 4.9 KB
/
object-oriented-programming.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# 面向对象编程 {#chap-object-oriented-programming}
进入这一章的读者都是对编程感兴趣的读者,希望在工程能力上有所提升的读者。那么最重要的是:
> Code should be written to minimize the time it would take for someone else to understand it.
>
> — The Art of Readable Code, Boswell, D. / Foucher, T.
代码可读性,代码复用性,代码维护性,代码扩展性,代码简洁性,代码高效性,代码容错性,我们共勉吧!如果读者已投身商业公司,应当以完成任务为第一,这自不必说!
## 环境 {#sec-environment}
```r
environment(fun = NULL)
environment(fun) <- value
is.environment(x)
.GlobalEnv
globalenv()
.BaseNamespaceEnv
emptyenv()
baseenv()
new.env(hash = TRUE, parent = parent.frame(), size = 29L)
parent.env(env)
parent.env(env) <- value
environmentName(env)
env.profile(env)
```
## 引用 {#sec-quote}
```r
get(x, pos = -1, envir = as.environment(pos), mode = "any",
inherits = TRUE)
mget(x, envir = as.environment(-1), mode = "any", ifnotfound,
inherits = FALSE)
dynGet(x, ifnotfound = , minframe = 1L, inherits = FALSE)
```
```r
get Return the Value of a Named Object
exists Is an Object Defined?
exists(x, where = -1, envir = , frame, mode = "any",
inherits = TRUE)
get0(x, envir = pos.to.env(-1L), mode = "any", inherits = TRUE,
ifnotfound = NULL)
```
## 调用栈 {#sec-call-stack}
Functions to Access the Function Call Stack
```r
sys.call(which = 0)
sys.frame(which = 0)
sys.nframe()
sys.function(which = 0)
sys.parent(n = 1)
sys.calls()
sys.frames()
sys.parents()
sys.on.exit()
sys.status()
parent.frame(n = 1)
sys.source Parse and Evaluate Expressions from a File
```
## 闭包 {#sec-closure}
An illustration of lexical scoping.
```r
demo(scoping)
```
## 递归 {#sec-recursion}
Using recursion for adaptive integration
```r
demo(recursion)
```
斐波那契数列
```{r}
# 递归 Recall
fibonacci <- function(n) {
if (n <= 2) {
if (n >= 0) 1 else 0
} else {
Recall(n - 1) + Recall(n - 2)
}
}
fibonacci(10) # 55
```
## 异常 {#sec-catching-and-handling-errors}
异常捕获和处理
```r
demo(error.catching)
```
## 对象 {#sec-is-things}
判断对象类型
```r
demo(is.things)
```
## 泛型 {#sec-generic}
> I'd like to prefix all these solutions with 'Here's how to do it, but don't actually do it you crazy fool'. It's on a par with redefining pi, or redefining '+'. And then redefining '<-'. These techniques have their proper place, and that would be in the currently non-existent obfuscated R contest. No, the R-ish (iRish?) way is to index vectors from 1. That's what the R gods intended!
>
> --- Barry Rowlingson [^BR-help-2004]
[^BR-help-2004]: <https://stat.ethz.ch/pipermail/r-help/2004-March/048688.html>
如果要让下标从 0 开始的话,我们需要在现有的向量类型 vector 上定义新的向量类型 vector0,在其上并且实现索引运算 `[` 和赋值修改元素的运算 `[<-`
```{r vector-index-zero}
# https://stat.ethz.ch/pipermail/r-help/2004-March/048682.html
as.vector0 <- function(x) structure(x, class = "vector0") # 创建一种新的数据结构 vector0
as.vector.vector0 <- function(x) unclass(x)
"[.vector0" <- function(x, i) as.vector0(as.vector.vector0(x)[i + 1]) # 索引操作
"[<-.vector0" <- function(x, i, value) { # 赋值操作
x <- as.vector.vector0(x)
x[i + 1] <- value
as.vector0(x)
}
print.vector0 <- function(x) print(as.vector.vector0(x)) # 实现 print 方法
```
举个例子看看
```{r test-index-zero}
1:10 # 是一个内置的现有向量类型 vector
x <- as.vector0(1:10) # 转化为新建的 vector0 类型
x[0:4] <- 100 * x[0:4] # 对 x 的元素替换修改
x
```
第三方 R 包大大扩展了 Base R 函数 `plot()` 的功能,比如 **mgcv** ,**nlme** 包和 **lattice** 包等,表 \@ref(tab:generic-functions) 列出当前环境下, `plot()` 绘图方法。
```{r generic-functions,echo=FALSE}
library(lattice)
library(nlme)
library(mgcv)
knitr::kable(matrix(methods("plot"), ncol = 3),
col.names = c("A", "B", "C"), caption = "泛型函数"
)
```
## 除虫 {#sec-code-debug}
[Debugging with RStudio](https://support.rstudio.com/hc/en-us/articles/205612627)
## 性能 {#sec-code-performance}
## 质量 {#sec-code-quality}
Github Action 提供的测试环境支持单元测试 testthat、静态代码检查 lintr、覆盖测试 covr、集成测试 Travis-CI、集成部署 Netlify 等一系列代码检查,还有额外的辅助工具,见 [Github Action 工具合集](https://github.com/sdras/awesome-actions),相关学习材料见快速参考手册 <https://github.com/github/actions-cheat-sheet> [PDF 版本](https://github.github.io/actions-cheat-sheet/actions-cheat-sheet.pdf),以创建 R 包为例,展示工程开发的流程 <https://mdneuzerling.com/post/data-science-workflows/>
标准计算和非标准计算 Standard and non-standard evaluation in R <https://www.brodieg.com/2020/05/05/on-nse/>