本文是AdvancedR的functions章节的总结


文章目录

  • function基础
  • 函数组成(function components)
  • 函数调用
  • 函数调用的组织方式
  • 函数参数懒求值(lazy evaluation)
  • 缺省参数
  • ...
  • 函数返回值
  • 退出函数处理函数exit handler
  • 函数形式(function forms)


function基础

  • function分为三部分:arguments, body, 和environment
# function的普通定义
function(arg1, arg2) { body } 
# 等价于
`function`(alist(arg1, arg2), body, env)
  • function是对象

函数组成(function components)

  • formals(f): 显示函数的参数定义。(采用args(f)更直观)
  • body(f): 显示函数的定义代码
  • environment(f): 显示该函数关联的环境

由于函数也是个对象,也有attribute,srcref属性包含所有的代码,包括注释。
attr(f, "srcref")

注意: primitive function(原始函数)是R语言中采用C语言实现的核心原始函数,为了提高运行效率。primitive function类型为builtin或special。上文的显示3个组成部分的函数都返回为NULL。

函数调用

do.call(fun, args)
等于fun(args)

函数调用的组织方式

除了常用的中间变量保存结果和嵌套调用外,magrittr包提供了一种管道(pipe)调用方式%>%

library(magrittr)
x %>%
deviation() %>%
square() %>%
mean() %>%
sqrt()

等价于嵌套调用方式:
sqrt(mean(square(deviation(x))))

函数参数懒求值(lazy evaluation)

和别的语言不同的是,函数的参数并非在调用的时候就计算好,然后传入函数;而是在函数内部执行的时候,遇到该参数,然后再根据传入的表达式进行计算。这就是所谓的lazy evaluation方式。
比如:

h01 <- function(x) {
10
}
h01(stop("This is an error!"))
#> [1] 10

由于参数x在函数内部没有用到,因此,stop("This is an error!")永远也不会执行。

lazy evalation是由一种叫做promise的机制实现的,一个promise包含三部分:

  • 一个表达式(An expression): 用于delayed compuation的表达式
  • 一个环境(An environment):该表达式计算时关联的环境
  • 一个值(A value):该表达式在关联环境中计算所得到的值,而且只计算一次,避免后续对该参数的引用会导致重复计算。

缺省参数

形式定义: func(x = express1, y = express2)

注意:express1, express2在参数缺失时也是lazy evaluation,不过需要注意的是,其关联的environment是该函数内部的environment。这和传入参数的environment是函数外的environment是不一样的。

函数内部可以使用missing()函数判断一个参数是否显式传入参数,返回TRUE或者FALSE。

变参(variable arguments)
使用…N的格式指明是第几个参数,比如:…1, …2 (比较罕见)

函数返回值

  • 隐式返回:最后一个表达式的值
  • 显式返回:使用return()函数

若在返回值放在invisible()函数中,则函数返回不可见,必须显示调用print或放在()中才能在命令行中显示出来。许多原始函数返回值都是不可见的,比如赋值函数: <-

退出函数处理函数exit handler

on.exit() 在函数内部可以使用on.exit(),注册一些函数完成清理或其他工作。

函数形式(function forms)

  • prefix: 前缀式
    普通的函数定义: func(a, b, c)
  • infix: 中缀式
    运算符和自定义运算符。
  • x + y: `+`(x, y)
  • x %op% y: `%op%`(x, y)
  • replacement:替换
    比如:属性赋值names(df) <- c("a", "b", "c") 等价于: `names<-`(df,c(“a”, “b”, “c”))
  • special: 特殊形式的函数,包括下标符号,控制语句等
    [[, if, for

如本文最开始所见,其实所有的形式,最后都翻译成统一的infix模式,包括function的普通定义:

function(arg1, arg2) {body} 
# 等价于
`function`(alist(arg1, arg2), body, env)