Я пишу пакет R и очень хотел бы избежать использования имен функций, найденных в других пакетах. Например, я планировал вызвать функцию «аннотировать», но это уже использовалось в пакете НЛП. Очевидно, что лучше избегать очевидного выбора имени, но существует ли систематический способ поиска в исчерпывающем списке опубликованных имен функций CRAN, чтобы избежать дублирования? Я понимаю, что это в первую очередь важно для общих пакетов CRAN, но это также может быть актуально при локальном обмене на случай конфликта с другим загруженным пакетом.
Именование функций для пакетов R
Ответы (1)
Конфликты имен возникают при загрузке двух пакетов, содержащих функции с одинаковыми именами. Таким образом, конфликтов имен можно избежать в двух местах:
- при определении имен функций в пакете
- при вызове функций из пакета
Создание функций с уникальными именами
На момент написания статьи (23 августа 2017 г.) в CRAN было доступно невероятное количество 11272 пакетов (последние данные можно найти здесь), и новые пакеты добавляются каждый день. а>.
Таким образом, создание уникальных имен функций сегодня может привести к конфликтам имен в будущем, когда будут добавлены другие пакеты.
Алистер уже упомянул возможность префикса всех ваших функций. Помимо stringi
и stringr
, пакеты forcats
являются еще одним примером, в котором используются префиксы fct_
и lvls_
.
Такой подход может значительно снизить вероятность конфликтов имен.
(Хотя не гарантируется, что никакой другой сопровождающий пакета не выберет тот же префикс.)
Однозначный вызов функций с использованием оператора двойного двоеточия
ИМХО, основная ответственность за предотвращение конфликтов имен лежит на пользователе.
Я видел вопросы здесь на SO с более чем полдюжиной загружаемых пакетов. Или для удобства вызывается library(tidyverse)
, что означает загрузку 19 других пакетов, тогда как dplyr
и tidyr
было бы достаточно.
Загромождение пространства имен большим количеством загруженных пакетов увеличивает риск конфликтов имен. И даже при загрузке только двух пакетов могут возникнуть конфликты имен. Например, в пакетах lubridate
и data.table
определены
hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year
Какая функция вызывается, зависит от порядка загрузки пакетов. (Вы можете использовать conflicts()
для поиска объектов, которые существуют с тем же именем в двух или более местах на пути поиска.)
Чтобы избежать двусмысленностей и неожиданных результатов, я предлагаю загружать как можно меньше пакетов и использовать оператор с двойным двоеточием ?"::"
для вызова функций из пакетов без предварительной загрузки пакета, например,
library(data.table)
DT <- data.table(t = lubridate::now() + 0:3)
# call function from loaded package data.table
DT[, second(t)]
[1] 18 19 20 21
# call function from lubridate package
DT[, lubridate::second(t)]
[1] 18.88337 19.88337 20.88337 21.88337
Есть еще одно преимущество использования оператора двойного двоеточия. Он будет служить документацией в коде, из которого вызывается функция.
Это происходит за счет нескольких дополнительных нажатий клавиш, но может сэкономить много времени, когда код проверяется, изменяется или отлаживается через недели или годы. Я видел много вопросов на SO, где ОП не упомянул пакет.
::
может привести к значительным накладным расходам. В моей системе x <- runif(100); microbenchmark(sum(x), base::sum(x))
это в 20 раз медленнее (правда, всего 5 микросекунд), но если вы делаете это со многими группами, как в DT[, base::sum(x), by=....]
, это проблема.
- person BrodieG; 23.08.2017
stri_*
), stringr (str_*
) и т. д. - person alistaire   schedule 23.08.2017