前言

总所周知,R语言有些神奇的赋值操作,
同一个函数既可以正常使用获取对象属性,
又可以给返回值赋值从而修改原对象的属性

names
下例实现了给对应元素一次性赋值name属性的功能。

> a = c(1,2)
> names(a) = c("张三","李四")
> names(a)
[1] "张三" "李四"
> a
张三 李四 
   1    2 
>

length

下例:length被主动赋值一个更小的数,实现了元素删除的效果。

> a
张三 李四 
   1    2 
> length(a)
[1] 2
> length(a) = 1
> a
张三 
   1 
> length(a)
[1] 1

虽然这并不符合常规的编程思想(至少我觉得很奇怪),但是这一功能确实简化了R语言使用者的操作,让精力真正放在统计工作当中。

那么问题来了:
R语言开发者,如何利用这一特性,帮助自己实现类似方法呢?

这个时候老师给我们提出一个问题
我们要如何实现一个函数first(a)
这个函数有两种用法
①first(a) 返回a的第一个元素
②first (a)<- value 将value赋值给a的第一个元素(覆盖)

一、直接尝试

我们先定义一个简单的first函数,获取第一个元素

> first = function(x)x[1]
> x = c(1,2,3,4)
> first(x)
[1] 1

然后我们仿照names的方式,尝试直接给first(c(1,2,3))赋值

> first(x) = 6
Error in first(x) = 6 : 没有"first<-"这个函数

显然,没有成功,但是其报错提示给了我一个线索"first<-“函数
我定义的函数确实不叫"first<-”,因此我猜测,如果需要对R语言函数的返回值赋值,需要先创建其对应的"函数名<-"函数

二、验证猜测

对于"first<-"这个函数,我猜测其函数功能就是将等号右侧的值当作参数传给函数并且实现赋值。
因此我构造如下方法:

> first<- = function(x,a){x[1]=a;x}
错误: 意外的'='在"first<- ="里

显然 <- 和 = 混用,R语言解释器无法正常理解这条语句
因此我想到用()、’’、""将first<- 分隔开,重新定义。

> (first<-) = function(x,a){x[1]=a;x}
错误: 意外的')'在"(first<-)"里
> 'first<-' = function(x,a){x[1]=a;x}
> "first<-" = function(x,a){x[1]=a;x}
>

显然,单引号、双引号都起到了隔离的作用,于是我开始验证其作用

> first(x) = 5
Error in `first<-`(`*tmp*`, value = 5) : 参数没有用(value = 5)

对于这个返回结果我感觉程序已经调用了"first<-"这个函数,但是还有什么地方出了问题。

找了许久,后面在参考names、length的说明文档中以及其报错信息中找到了灵感

R语言中session作用 r语言response_开发者


R语言中session作用 r语言response_开发者_02

参数没有用(value = 5)

三、解决方案

我传给这种特殊方法的参数值名称为value,但是我调用的时候只调用了自己定义的a参数,因此仅需将a参数改成value即可。

"first<-" = function(x,value){x[1]=value;x}

完整代码演示:

> first = function(x){x[1]}
> "first<-" = function(x,value){x[1]=value;x}
> x = c(1,2,3,4)
> first(x)
[1] 1
> first(x) = 5 //给函数返回值赋值
> first(x) 
[1] 5  //赋值成功
> x
[1] 5 2 3 4

四、后记

解决这个问题的过程中,发现网上对于R语言的资料远不如Java、Python等语言。像R语言这样类似的细节问题更难找到解决方案,在今后的学习过程中,还需要多多实践,如果能多看看官方文档也许能更系统的学习。