Подтвердить что ты не робот

Отключить назначение через = в R

R позволяет назначать через <- и =.

В то время как между двумя операторами присваивания тонкие различия, похоже, существует широкий консенсус в отношении того, что <- является лучшим выбором, чем =, поскольку = также используется в качестве значений отображения операторов для аргументов, и поэтому его использование может привести к неоднозначным утверждениям. Ниже приведен пример:

> system.time(x <- rnorm(10))
   user  system elapsed 
      0       0       0 
> system.time(x = rnorm(10))
Error in system.time(x = rnorm(10)) : unused argument(s) (x = rnorm(10))

Фактически код стиля Google запрещает использование = для назначения (см. комментарии к этому ответ для обратного просмотра).

Я также почти исключительно использую <- как оператор присваивания. Тем не менее, почти в предыдущем предложении есть причина этого вопроса. Когда = действует как оператор присваивания в моем коде, он всегда случайный, и если это приводит к проблемам, то их обычно трудно обнаружить.

Я хотел бы знать, есть ли способ отключить назначение через =, и пусть R выдает ошибку в любое время = для назначения.

Оптимально это поведение произойдет только для кода в глобальной среде, так как может быть код в прикрепленных пространствах имен, который использует = для назначения и не должен прерываться.

(Этот вопрос был вдохновлен обсуждением Джонатан Нельсон)

4b9b3361

Ответ 1

Здесь кандидат:

`=` <- function(...) stop("Assignment by = disabled, use <- instead")
# seems to work
a = 1
Error in a = 1 : Assignment by = disabled, use <- instead
# appears not to break named arguments
sum(1:2,na.rm=TRUE)
[1] 3

Ответ 2

Я не уверен, но, возможно, просто переписать назначение = достаточно для вас. В конце концов, `=` - это имя, как и любое другое - почти.

> `=` <- function() { }
> a = 3
Error in a = 3 : unused argument(s) (a, 3)
> a <- 3
> data.frame(a = 3)
  a
1 3

Таким образом, любое использование = для назначения приведет к ошибке, тогда как использование его для обозначения аргументов остается в силе. Его использование в функциях может остаться незамеченным, если только соответствующая строка не будет выполнена.

Ответ 3

В пакете lint (CRAN) есть проверка стиля для этого, поэтому, предположим, что у вас есть код в файле, вы можете запустить lint против него, и он предупредит вас об этих номерах строк с = присваиваниями.

Вот пример:

temp <- tempfile()
write("foo = function(...) {
          good <- 0
          bad = 1
          sum(..., na.rm = TRUE)
       }", file = temp)

library(lint) 
lint(file = temp, style = list(styles.assignment.noeq))
# Lint checking: C:\Users\flodel\AppData\Local\Temp\RtmpwF3pZ6\file19ac3b66b81
# Lint: Equal sign assignemnts: found on lines 1, 3

Пакет lint поставляется с еще несколькими тестами, которые могут вам показаться интересными, в том числе:

  • предупреждает о правильных назначениях
  • рекомендует пробелы вокруг =
  • рекомендует пробелы после запятых
  • рекомендует пробелы между инфиксами (двоичные операторы a.k.a.)
  • предупреждает о вкладах
  • возможность предупреждения против максимальной ширины линии
  • предупреждает о назначении внутри вызовов функций

Вы можете включить или выключить любую предопределенную проверку стиля, и вы можете написать свой собственный. Однако пакет все еще находится в зачаточном состоянии: он содержит несколько ошибок (https://github.com/halpo/lint), и документация немного сложна для переваривания. Автор реагирует хотя и медленно делает улучшения.

Ответ 4

Если вы не хотите разорвать существующий код, что-то вроде этого (печатать предупреждение, а не ошибку) может работать - вы даете предупреждение, затем назначаете parent.frame с помощью <- (чтобы избежать какой-либо рекурсии)

`=` <- function(...){
        .what <- as.list(match.call())
        .call <-  sprintf('%s <- %s', deparse(.what[[2]]),  deparse(.what[[3]]))
        mess <- 'Use <- instead of = for assigment '
        if(getOption('warn_assign', default = T)) {
        stop (mess) } else {
        warning(mess)
        eval(parse(text =.call), envir = parent.frame())  
          }
        }

Если вы установите options(warn_assign = F), тогда = будет предупреждать и назначать. Все остальное выкинет ошибку и не назначит.

примеры использования

# with no option set
z = 1
## Error in z = 1 : Use <- instead of = for assigment 
options(warn_assign = T)
z = 1
## Error in z = 1 : Use <- instead of = for assigment 
 options(warn_assign = F)
 z = 1
## Warning message:
##  In z = 1 : Use <- instead of = for assigment 

Улучшенные параметры

Я думаю, что formatR или lint и форматирование кода лучше подходят.