Comments 8
Честно говоря, особенности R
проявляются только в части пунктов. Расположение фигурных скобок, спейсинг и пробелы vs табуляция порождают конфликты вокруг, кажется, любого языка. Но хотелось бы добавить несколько вещей.
1) Псевдооператор `:=`
из пакетов семества tidy
. Вызов оператора отваливается с ошибкой, но он по-особому интерпретируется механизмом цитирования rlang
и по сути означает присваивание:
> quos(!!paste0("x", "y") := 5)
#
<list_of<quosure>>
$xy
<quosure>
expr: ^5
env: empty
2) По-хорошему, использование оператора <-
в списке аргументов функций должено считаться плохой практикой. <-
используется для присваивания значений в текущем окружении, поэтому проблемы можно получить в редком случае, когда x <- 5
записан как x < -5
. К сожалению, синтаксис валидный и ошибки инетрпретации вы не получите. В качестве альтернативы можно окунуться в функциональный подход. Тогда присваивание будет последним действием: x %>% do_job %>% do_more(with_param) -> y
, но с точки зрения читабельности возникают вопросы.
3) Имена функций и переменных. Честно говоря, базовые пакеты, написанные статистиками, это какой-то ад. Конвенции попросту отсутствуют, а запомнить какие-то особые аргументы просто невозможно (мне вспоминается дурацкий na.rm
, который я вечно пишу как rm.na
). Имена с точками, которые есть и в базовом пакете, могут привести к проблемам с дженериками, т.к. .class_name
постфикс используется для указания типа. Например, стандартный data.frame
имеет оператор преобразования as: as.data.frame
, в соответствии с соглашением об is
и as
операторах. Так вот, если применить этот метод к data.frame
, то на деле вызовется… as.data.frame.data.frame
, и это валидная существующая функция, которую вы можете проверить.
Собственно это одна из причин, по которой tidyverse
использует lowercase с underscore.
:=
был оператором присвоения только в ранних версиях R. Сейчас в base такого оператора больше нет, а значит его вызов и не должен работать. Но токен :=
остался в коде R как LEFT_ASSIGN
(см. source code). А раз есть токен, то
:=
можно использовать как инфиксный оператор, не прибегая к формату %function_name%
. Таким образом, его использование в коллекции tidy правомерное, хотя это своего рода хак. Да и не только там :=
встречается: в data.table он тоже есть. По-хорошему, использование оператора <-
в списке аргументов функций должено считаться плохой практикой.
С этим полностью согласен: глобального присвоения следует избегать. Поэтому оправданной будет конвенция =
для параметров функции, <-
для всего остального.Из-за непопулярности _ функции такого стиля почти не встречаются среди базовых:
Да и мучительно привыкать к написанию seq_along()
с оператором %>% тоже регулярно путаница в dplyr и tidyverse
<-
вместо =
? По мне — написать что-то типа func_name(x <- 5)
— хороший повод получить канделябром от коллеги, ибо не особо очевидно зачем так делать. А если так не делать, то почему не использовать повсеместно просто знак равенства?Если посмотреть кернелы кагла, видно, что там R — в районе 5-10%. Для меня это показатель, что человек, занимающийся анализом данных на R и не желающий оказаться позади, должен как минимум понимать python. А если так — почему не использовать знак
=
для присвоения и в R, раз он работает в обоих языках?И да, внутри функции всё-таки лучше использовать
=
. Просто этот пример наглядно демонстрирует, что назначение параметра функции и присвоение значения — не одно и тоже. В вашем примере func_name(x <- 5)
будет обработано всегда, а вот func_name(x = 5)
только если x является параметром функции.Не совсем понимаю, что значит "x <- 5
будет обработано всегда". Присваивание с одновременной передачей параметра снижает читаемость и поэтому считается плохим тоном, его надо избегать. А вариант с x = 5
упадет с ошибкой, если x
не является параметром функции и это очень правильно. Сам я всегда стараюсь писать =
, потому что никаких рациональных доводов в пользу стрелочки нет, только традиции. Против неё описанная вами ситуация со сравнением x<-5
. То есть, с моей точки зрения, 1:0 в пользу =
.
mean(some_var_name <- 1:5)
будет обработано корректно, а mean(some_var_name = 1:5)
выдаст ошибку т.к. название аргумента у этой функции х. (Сам не одобряю практику использования стрелки внутри функции, просто как иллюстрация возможности)
Занимательная археология: стилевое руководство R под лупой