点在R –个人喜好,命名约定或更多内容中意味着什么?


76

我(可能)不是var1~.在这里指“所有其他变量” 。plyr再次指向我,调查mlply并想知道为什么用这样的前导点定义参数:

function (.data, .fun = NULL, ..., .expand = TRUE, .progress = "none", 
.parallel = FALSE) 
{
if (is.matrix(.data) & !is.list(.data)) 
    .data <- .matrix_to_df(.data)
f <- splat(.fun)
alply(.data = .data, .margins = 1, .fun = f, ..., .expand = .expand, 
    .progress = .progress, .parallel = .parallel)
}
<environment: namespace:plyr>

这有什么用?仅仅是个人喜好,命名约定还是更多?R通常功能如此强大,以至于我错过了一个早已完成的技巧。


5
好问题。同样,在其他编程语言中,在函数名称(is.na,,as.data.frame...)中使用点也不常见,但我喜欢它。
TMS


purrr封装(purrr.tidyverse.org)现在增加意味着作为另一层~ .x+1== function(x) x+1
同构

1
如果键盘将琴键放置_在易于到达的位置(例如,您知道,而不是Shopping琴键...),那么可以解决很多这种混乱情况
同构

Answers:


116

函数名称中的点可以表示以下任何一项:

  • 一点都没有
  • S3方法中方法和类之间的分隔符
  • 隐藏函数名称

可能的含义

1.什么都没有

在该点data.frame不开data距离frame,除了在视觉上。

2. S3方法中的方法和类的分离

plot是通用S3方法的一个示例。因此,plot.lmplot.glm是调用plot(lm(...))或调用时使用的基础函数定义。plot(glm(...))

3.隐藏内部功能

编写程序包时,有时在函数名称中使用前导点很有用,因为这些函数在一般视图中有些隐藏。纯粹是包内部的功能有时会使用此功能。

在这种情况下,“有点隐藏”只是意味着当您使用列出对象时,变量(或函数)通常不会显示ls()。要强制ls显示这些变量,请使用ls(all.names=TRUE)。通过使用点作为变量的首字母,可以更改变量本身的范围。例如:

x <- 3
.x <- 4

ls()
[1] "x"

ls(all.names=TRUE)
[1] ".x" "x" 

x
[1] 3
.x
[1] 4

4.其他可能的原因

在哈德利的 包中,他使用约定在函数名称中使用前导点。这是一种尝试确保在解析变量名时将值解析为用户变量而不是内部函数变量的机制。


并发症

不同用途的混合使用会导致非常混乱的情况,因为这些不同用途都可能混入同一函数名称中。

例如,要将a转换为data.frame您使用的列表as.list(..)

as.list(iris)

在这种情况下,as.list将使用S3泛型方法,并将其传递data.frame给它。因此,S3函数称为as.list.data.frame

> as.list.data.frame
function (x, ...) 
{
    x <- unclass(x)
    attr(x, "row.names") <- NULL
    x
}
<environment: namespace:base>

对于真正引人入胜的东西,请加载data.table包装并查看其功能as.data.table.data.frame

> library(data.table)

> methods(as.data.table)
[1] as.data.table.data.frame* as.data.table.data.table* as.data.table.matrix*    

   Non-visible functions are asterisked


> data.table:::as.data.table.data.frame
function (x, keep.rownames = FALSE) 
{
    if (keep.rownames) 
        return(data.table(rn = rownames(x), x, keep.rownames = FALSE))
    attr(x, "row.names") = .set_row_names(nrow(x))
    class(x) = c("data.table", "data.frame")
    x
}
<environment: namespace:data.table>

“什么隐藏”是什么意思?点不改变变量范围,对吗?因此,仅在用户通常不在变量名开头使用点的意义上隐藏它,对吗?
TMS

@TomasT。我已经编辑了答案。是的,添加点会更改范围,因此x.x是不同的变量。虚线变量是隐藏的,因为ls除非您使用,否则它们不会出现在其中ls(all.names=TRUE)
Andrie

1
哦,我明白你的意思。不是的,因为范围的行为x.x是相同的。它们恰好是不同的变量。
Andrie

3
我只在plyr中这样做,因为您要区分plyr函数的参数和plyr调用的函数的参数。
hadley 2011年

3
plyr也具有.功能。get(".") ; function (..., .env = parent.frame()) { structure(as.list(match.call()[-1]), env = .env, class = "quoted") }
baptiste

28

名称的开头类似于UNIX文件名约定,默认情况下将对象隐藏。

ls()
character(0)

.a <- 1

ls()
character(0)

ls(all.names = TRUE)
[1] ".a"

它可以只是一个没有特殊含义的令牌,它所做的不过是任何其他允许的令牌。

my.var <- 1
my_var <- 1
myVar <- 1

用于S3方法分派。因此,如果我定义简单的类“ myClass”并使用该类属性创建对象,则诸如print()之类的通用函数将自动分派到我的特定打印方法。

myvar <- 1

print(myvar)

class(myvar) <- c("myClass", class(myvar))

print.myClass <- function(x, ...) {

    print(paste("a special message for myClass objects, this one has length", length(x)))
    return(invisible(NULL))
}

print(myvar)

S3的语法含糊不清,因为您无法从函数名称中分辨出它是S3方法还是名称中的点。但是,这是一个非常简单的机制,功能非常强大。

这三个方面还有很多,您不应该将我的示例作为良好的实践,但它们是基本的区别。


3
为什么要隐藏一些不是全局的对象?
马特·班纳特

3
您还可以将变量或函数定义为单个点!喜欢.=1.(1)。这真的很奇怪,尤其是在表达式中.*.+.:-)
TMS

0

如果用户定义了一个函数.doSomething,并且懒于为参数指定所有roxygen文档,那么它将不会在编译程序包时产生错误

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.