Pull to refresh

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, раз он работает в обоих языках?
В самом начале это давало обратную совместимость с S и S-PLUS. Сейчас особого смысла здесь нет: исключительно традиция. И поскольку 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) выдаст ошибку т.к. название аргумента у этой функции х.
(Сам не одобряю практику использования стрелки внутри функции, просто как иллюстрация возможности)

С моей точки зрения корректное поведение — выдача ошибки. Допустим, есть такая функция: f = function(x = NA, y = NA) {cat("x = ", x, "y = ", y, "\n")}, тогда f(y <- 25) выдаст x = 25 y = NA. Понятно, почему так происходит, но это явно не про читаемость.

Sign up to leave a comment.

Articles