在个人偏好中,点是什么意思? 变数命名原则还是更多?

我(可能)不是指“所有其他变量”的意思像 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 是如此的功能性,以至于我错过了一个很久以前就已经做过的技巧。

34391 次浏览

At the start of a name it works like the UNIX filename convention to keep objects hidden by default.

ls()
character(0)


.a <- 1


ls()
character(0)


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

It can be just a token with no special meaning, it's not doing anything more than any other allowed token.

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

It's used for S3 method dispatch. So, if I define simple class "myClass" and create objects with that class attribute, then generic functions such as print() will automatically dispatch to my specific print method.

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)

There is an ambiguity in the syntax for S3, since you cannot tell from a function's name whether it is an S3 method or just a dot in the name. But, it's a very simple mechanism that is very powerful.

There's a lot more to each of these three aspects, and you should not take my examples as good practice, but they are the basic differences.

A dot in function name can mean any of the following:

  • nothing at all
  • a separator between method and class in S3 methods
  • to hide the function name

Possible meanings

1. Nothing at all

The dot in data.frame doesn't separate data from frame, other than visually.

2. Separation of methods and classes in S3 methods

plot is one example of a generic S3 method. Thus plot.lm and plot.glm are the underlying function definitions that are used when calling plot(lm(...)) or plot(glm(...))

3. To hide internal functions

When writing packages, it is sometimes useful to use leading dots in function names because these functions are somewhat hidden from general view. Functions that are meant to be purely internal to a package sometimes use this.

In this context, "somewhat hidden" simply means that the variable (or function) won't normally show up when you list object with ls(). To force ls to show these variables, use ls(all.names=TRUE). By using a dot as first letter of a variable, you change the scope of the variable itself. For example:

x <- 3
.x <- 4


ls()
[1] "x"


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


x
[1] 3
.x
[1] 4

4. Other possible reasons

In Hadley's package, he uses the convention to use leading dots in function names. This as a mechanism to try and ensure that when resolving variable names, the values resolve to the user variables rather than internal function variables.


Complications

This mishmash of different uses can lead to very confusing situations, because these different uses can all get mixed up in the same function name.

For example, to convert a data.frame to a list you use as.list(..)

as.list(iris)

In this case as.list is a S3 generic method, and you are passing a data.frame to it. Thus the S3 function is called as.list.data.frame:

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

And for something truly spectacular, load the data.table package and look at the function 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>

If a user defines a function .doSomething and is lazy to specify all the roxygen documentation for parameters, it will not generate errors for compiling the package