
Комментарии 8
Честно говоря, особенности R проявляются только в части пунктов. Расположение фигурных скобок, спейсинг и пробелы vs табуляция порождают конфликты вокруг, кажется, любого языка. Но хотелось бы добавить несколько вещей.
1) Псевдооператор `:=` из пакетов семества tidy. Вызов оператора отваливается с ошибкой, но он по-особому интерпретируется механизмом цитирования rlang и по сути означает присваивание:
> quos(!!paste0("x", "y") := 5)
#
<list_of<quosure>>
$xy
<quosure>
expr: ^5
env: empty2) По-хорошему, использование оператора <- в списке аргументов функций должено считаться плохой практикой. <- используется для присваивания значений в текущем окружении, поэтому проблемы можно получить в редком случае, когда 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 под лупой