4. 函数

作者: kkkkkkang | 来源:发表于2020-04-15 15:44 被阅读0次

Ok,开始新的一章。基本的我就不写了,只写应该注意的地方和坑。代码基本都是来源于书上,少部分是我自己加上去的

  • 重新开始(别误会,是函数)
> j <- function() {
  if (!exists("a")) {
    a <- 1
  } else {
    a <- a + 1
  }
  a
}
> j()
[1] 1
> j()
[1] 1
#因为每次调用这个函数都会创建一个新环境,函数不可能知道上次被调用时发生了什么,每次调用都是独立的
  • 动态查找,这个地方可以用来使坏😈
> f <- function() x
> x <- 15
> f()
[1] 15
> x <- 20
> f()
[1] 20
#然而,这样函数就不是独立的了,可以使用codetools::findGlobals()查看一个函数额所有外界依赖关系
> f <- function() x + 1
> codetools::findGlobals(f)
[1] "+" "x"
#使用emptyenv()清空环境不现实,这样你连"+"都用不了了。所以这样别人就有可能使坏了
#比如:趁你不在,把"("的这个函数给改掉—有1/10的概率得到比输入值大1的数
> `(` <- function(e1) {
  if (is.numeric(e1) && runif(1) < 0.1) {
    e1 + 1
  } else {
    e1
  }
}
> replicate(50, (1 + 2))
> replicate(50, (1 + 2))
 [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 3 3 3 3 3 3 3 4 3 3 3 3 4 3 3 3 3 3 3 3 3 3
[39] 3 3 3 3 3 3 4 3 3 3 4 3
#看看,是的吧。解决方法很简单
> rm("(")
> replicate(50, (1 + 2))
 [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
[39] 3 3 3 3 3 3 3 3 3 3 3 3
#重归于好,哈哈哈。这里不是教人使坏,其实是警示大家在开始R会话之前,尽量清空之前对话的数据
> rm(list = ls())
  • 习题
> f <- function(x) {
+     f <- function(x) {
+         f <- function(x) {
+             x ^ 2
+         }
+         f(x) + 1
+     }
+     f(x) * 2
+ }
> f(10)
#在脑子里过一下这个会得到什么结果
好吧,答案是202
#解答思路:最内层函数要向外找变量值10,f(x) +1 值就成了101,然后f(x)*2就是202
  • 自定义中缀运算符及其优先级调整策略
> `%foo%` <- `+`
> 2 %foo% 4
[1] 6
> `%mul%` <- `*`
> 2 %foo% 4 %mul% 3
[1] 18
#默认优先级是从左到右的,调整优先级,加括号就行了
> 2 %foo% (4 %mul% 3)
[1] 14
  • 中缀函数:一般都是函数在参数的前面,可以使用中缀函数把函数放到参数的中间。另外我们可以自定义并且利用`(tab键上面的那个) 引用预留的或自定义(非法)的函数
> `%mul%`(3,4)
[1] 12
x <- 10; y <- 5
x + y
#> [1] 15
`+`(x, y)
#> [1] 15

for (i in 1:2) print(i)
#> [1] 1
#> [1] 2
`for`(i, 1:2, print(i))
#> [1] 1
#> [1] 2

if (i == 1) print("yes!") else print("no.")
#> [1] "no."
`if`(i == 1, print("yes!"), print("no."))
#> [1] "no."

x[3]
#> [1] NA
`[`(x, 3)
#> [1] NA

{ print(1); print(2); print(3) }
#> [1] 1
#> [1] 2
#> [1] 3
`{`(print(1), print(2), print(3))
#> [1] 1
#> [1] 2
#> [1] 3

上面这个思想和apply结合可以自编函数来处理每个元素,实现想要的功能

> add <- function(x, y) x + y
> sapply(1:10, add, 3)
 [1]  4  5  6  7  8  9 10 11 12 13
> sapply(1:5, `+`, 3)
[1] 4 5 6 7 8
> sapply(1:5, "+", 3)
[1] 4 5 6 7 8
> x <- list(1:3, 4:9, 10:12)
> sapply(x, "[", 2)
[1]  2  5 11
> sapply(x, function(x) x[2])
[1]  2  5 11
  • 函数参数
#使用参数列表来传递函数参数
> args <- list(1:10, na.rm = TRUE)
> do.call(mean, args)
[1] 5.5
#等同于
> mean(1:10,na.rm = TRUE)
[1] 5.5
#默认参数
> f <- function(a = 1, b = 2) {
  c(a, b)
}
> f()
#> [1] 1 2
#默认参数可以使用其它参数来求值
g <- function(a = 1, b = a * 2) {
  c(a, b)
}
g()
#> [1] 1 2
g(10)
#> [1] 10 20
#默认参数甚至可以是隐藏在函数内部的变量(这并不推荐)
h <- function(a = 1, b = d) {
  d <- (a + 1) ^ 2
  c(a, b)
}
h()
#> [1] 1 4
h(10)
#> [1]  10 121
#像上面这种,默认参数需要很长的计算才能得到,通常建议使用missing()函数判断,有需要再计算。
#缺点:不阅读文档就不知道那个参数是必须的。可以把默认参数设置成NULL,is.null()去判断参数是否设置了
  • 终止函数stop()
> a <- function(x){
  for (i in 1:x){
    print(i)
    if (i == 3){
      stop("Error:3 is an error number")
    }
  }
}
> a(4)
[1] 1
[1] 2
[1] 3
Error in a(4) : Error:3 is an error number
  • 惰性求值,即只在使用函数参数时,对其求值;有时可以用来删除一个if语句
> f <- function(a,b){
+   print(a)
+ }
> f(2)
[1] 2
> f_1 <- function(a,b){
+   print(a)
+   print(b)
+ }
> f_1(8)
[1] 8
Error in print(b) : 缺少参数"b",也没有缺省值
************************************************************
> a <- NULL
> if (is.null(a)) stop("a is null")
错误: a is null
> !is.null(a) || stop("a is null")
错误: a is null
> is.null(a) || stop("a is null")
[1] TRUE

...参数:它可以传递一个函数的参数到另一个函数(可以利用这个特性修改已知函数的参数,而不必列出所有原函数的参数);当传递到函数的参数数量不能确定的时候,它必须被使用

#用来传参
> new_plot <- function(x,y,type = "s",...){
  plot(x,y,...)
}
#参数个数不确定
> num <- function(...,sep = "_"){
+   paste(...,sep = sep)
+ }
> num(1,2,3)
[1] "1_2_3"
  • 对函数的参数进行修改,不会改变参数的原始值
> f <- function(x) {
+     x$a <- 2
+     x
+ }
> x <- list(a = 1)
> f(x)
$a
[1] 2
> x$a
[1] 1
  • invisible()函数详解
f1 <- function() 1
f2 <- function() invisible(1)
f1()
#> [1] 1
f2()
f1() == 1
#> [1] TRUE
f2() == 1
#> [1] TRUE
********************************************************
#可以使用括号,强制显示
(f2())
#> [1] 1
#最常用的隐藏返回值的函数应该是"<- "了,这样可以把一个值赋给多个变量
a <- b <- c <- d <- 2

on.exit()前面一章已经说过了,需要注意的是:如果在一个函数中使用多个on.exit(),一定要加上参数add = TRUE。不加的话,每次运行on.exit()后,它将重写退出表达式

相关文章

  • 4.函数

    函数 1 创建函数与调用 1.1 lambda函数 python允许使用lambda关键字创建匿名函数。lambd...

  • 4.函数

    数据类型转换 Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数: ...

  • 4. 函数

    Ok,开始新的一章。基本的我就不写了,只写应该注意的地方和坑。代码基本都是来源于书上,少部分是我自己加上去的 重新...

  • 4.函数

    ①写函数的函数

  • 4.函数

    倒U函数 波动函数 指数函数 对数函数 玻璃顶 送外卖 共享单车 嫩模 产品效率只和广告投入有关 凹形幂函数

  • dplyr

    1. filter 函数 2. arrange() 函数 3. select 函数 4. mutate() 函数 ...

  • 4.常见函数

    绑定事件通用性方法:

  • 4. PHP函数

    思考:在开发过程中会有很多代码其实是重复的,只是其中有一点点数据的变化,那么这样的代码我们是通过复制-粘贴-修改部...

  • Swift-函数

    简单函数 1.函数 2.函数参数 3.外部参数 4.函数返回值

  • js总结(4.函数)

    函数 ** 1.函数** 2.定义函数 3.定义带参函数 4.带有返回值的函数

网友评论

    本文标题:4. 函数

    本文链接:https://www.haomeiwen.com/subject/qgexvhtx.html