R стиль письма - требовать против :: - PullRequest
19 голосов
/ 07 декабря 2010

Хорошо, мы все знакомы с оператором двойного двоеточия в R. Всякий раз, когда я собираюсь написать какую-то функцию, я использую require(<pkgname>), но я всегда думал об использовании :: вместо этого.Использование require в пользовательских функциях лучше, чем library, поскольку require возвращает предупреждение, а FALSE, в отличие от library, возвращает ошибку, если вы указали имя несуществующего пакета.

С другой стороны, оператор :: получает переменную из пакета, в то время как require загружает весь пакет (по крайней мере, я на это надеюсь), поэтому различие в скорости пришло мне в голову.:: должен быть быстрее, чем require.

И я провел некоторый анализ, чтобы проверить это - я написал две простые функции, которые загружают функцию read.systat из пакета foreign, с require и :: соответственно, следовательно, импортируйте набор данных Iris.syd, который поставляется с пакетом foreign, реплицировали функции 1000 раз каждая (что было бессовестно произвольно) и ... сократили некоторые числа.

Странно (илинет) Я обнаружил существенные различия с точки зрения пользовательского процессора и прошедшего времени, в то время как не было никаких существенных различий с точки зрения системного процессора.И еще более странный вывод: :: на самом деле медленнее!Документация для :: очень тупая, и, просто взглянув на источники, становится очевидным, что :: должен работать лучше!

требуют

#!/usr/local/bin/r

## with require
fn1 <- function() {
  require(foreign)
  read.systat("Iris.syd", to.data.frame=TRUE)
}

## times
n <- 1e3

sink("require.txt")
print(t(replicate(n, system.time(fn1()))))
sink()

двойное двоеточие

#!/usr/local/bin/r

## with ::
fn2 <- function() {
  foreign::read.systat("Iris.syd", to.data.frame=TRUE)
}

## times
n <- 1e3


sink("double_colon.txt")
print(t(replicate(n, system.time(fn2()))))
sink()

Получить данные CSV здесь .Некоторые характеристики:

user CPU:     W = 475366    p-value = 0.04738  MRr =  975.866    MRc = 1025.134
system CPU:   W = 503312.5  p-value = 0.7305   MRr = 1003.8125   MRc =  997.1875
elapsed time: W = 403299.5  p-value < 2.2e-16  MRr =  903.7995   MRc = 1097.2005

MRr - средний ранг для require, MRc там же для ::.Должно быть, я сделал что-то не так здесь.Это просто не имеет никакого смысла ... Время выполнения для :: кажется намного быстрее !!!Возможно, я что-то напортачил, вы не должны отказываться от этого варианта ...

ОК ... Я потратил впустую свое время, чтобы увидеть, что есть какая-то разница, и я провел совершенно бесполезный анализИтак, вернемся к вопросу:

" Почему при написании функции следует предпочесть require над ::? "

=)

Ответы [ 2 ]

12 голосов
/ 07 декабря 2010

"Почему при написании функции нужно отдавать предпочтение over ::"

Я обычно предпочитаю require из-за хорошего возвращаемого значения TRUE / FALSE, которое позволяет мне иметь дело свероятность того, что пакет не будет доступен заранее, прежде чем он попадет в код.Сбой как можно раньше, а не на полпути в вашем анализе.

Я использую :: только когда мне нужно убедиться, что я использую правильную версию функции, а не версию из какого-то другого пакета, который маскируетимя.

С другой стороны, :: operator получает переменную из пакета, в то время как require загружает весь пакет (по крайней мере, я на это надеюсь), поэтому сначала мне пришла разница в скорости.:: должно быть быстрее, чем требуется.

Я думаю, вы можете игнорировать эффекты отложенная загрузка , которая используется пакетом foreign в соответствии с первымстраница его руководства .По сути, пакеты, которые используют отложенную загрузку, откладывают загрузку объектов, таких как функции, до тех пор, пока объекты не будут вызваны в первый раз.Поэтому ваш аргумент, что «:: должен быть быстрее, чем требуется», не обязательно верен, поскольку foreign не загружает все его содержимое в память, когда вы присоединяете его с помощью require.Для получения полной информации о отложенной загрузке см. Prof.Статья Рипли в RNews, том 4, выпуск 2.

6 голосов
/ 07 декабря 2010

Поскольку время загрузки пакета почти всегда мало по сравнению со временем, которое вы тратите, пытаясь выяснить, о чем писал код, который вы написали шесть месяцев назад, в этом случае кодирование для ясности является наиболее важной вещью.

Для сценариев вызов на require или library в начале позволяет сразу узнать, какие пакеты вам нужны.

Аналогично, вызов require (или оболочки типа requirePackageв Hmisc или try_require в ggplot2) в начале функции - самый недвусмысленный способ показать, что вам нужно использовать этот пакет.

:: следует зарезервировать для случаев, когда выконфликты имен между пакетами - сравните, например,

Hmisc::is.discrete

и

plyr::is.discrete
...