Home Comments Thread
New Thread

25 Comments

giscus-bot giscus-bot 2022-12-16 23:56:36
Guest *Kun Ren* @ 2014-07-27 13:26:41 originally posted:

Thanks for your explanation! By the way, do you think it is a good practice to use "foo::bar()", as I asked on stackoverflow (http://stackoverflow.com/questions/23232791/is-it-a-good-practice-to-call-functions-in-a-package-via)?

@renkun-ken

yihui yihui 2022-12-16 23:59:00

I agree with the answer there. It really depends on the context: whether you are developing an R package, or just writing an R script; whether you have to type "foo::" many times, etc.

Originally posted on 2014-07-28 02:19:33

giscus-bot giscus-bot 2022-12-16 23:56:37
Guest *Jacob Westfall* @ 2014-07-27 18:38:28 originally posted:

I guess the moral is that when it comes to loading packages, "Try not! Do, or do not. There is no try."

giscus-bot giscus-bot 2022-12-16 23:58:38
Guest *duk* @ 2014-07-27 20:48:20 originally posted:

Nice post, thanks.

giscus-bot giscus-bot 2022-12-16 23:58:39
Guest *anthony damico* @ 2014-07-27 21:09:45 originally posted:

thank you

giscus-bot giscus-bot 2022-12-16 23:58:40
Guest *Guansong Wang* @ 2014-07-27 21:46:00 originally posted:

I agree it's pointless to use require() most of time. However, it's nice to be able to do something conditionally on the existence of some libraries, especially when I want to share the script/function.
For example, I use require() to load "multicore" (yes, quotations!). Then it will still run when someone wants to test it and doesn't have the packages installed.

yihui yihui 2022-12-16 23:58:59

Oh sure. I completely agree. I did not say require() should be forbidden in any cases.

Originally posted on 2014-07-28 02:14:52

giscus-bot giscus-bot 2022-12-16 23:58:41
Guest *Linlin Yan* @ 2014-07-27 23:21:04 originally posted:

+1 and I confess that I was making the same mistake! Thanks!

@yanlinlin82

giscus-bot giscus-bot 2022-12-16 23:58:42
Guest *Tal Galili* @ 2014-07-28 12:24:26 originally posted:

Dear Yihui - thank you for a GREAT post (as usual).

I admit that I didn't know (or forgot) that library gives an Error (when the package is not loaded) - so yay for learning something new!

One more (meaningless, and unimportant) reason I like (or liked) using require is that (for me) it is just faster to type (since all the letters for "require" are on the same keyboard row, as opposed to "library").

Yours,
Tal

yihui yihui 2022-12-16 23:59:02

Okay, tell me honestly: do you save these few seconds for playing 1024 or working on your dissertation? :-D

Originally posted on 2014-07-28 18:50:07

giscus-bot giscus-bot 2022-12-16 23:59:04
Guest *Tal Galili* @ 2014-07-29 08:42:15 originally posted:

More like fixing all of my require->to->library in dendextend :P

talgalili/dendextend@e676951

giscus-bot giscus-bot 2022-12-16 23:58:43
Guest *Justace Clutter* @ 2014-07-28 13:15:19 originally posted:

One... I agree with everything here.

Now, let me just jump in here and say.... "Love the videos...." I was just sitting in my office chair here laughing. Great start to a Monday morning! Learned something new and got a smile out of it.

giscus-bot giscus-bot 2022-12-16 23:58:44
Guest *Aleksandr Blekh* @ 2014-07-28 13:49:57 originally posted:

Interesting post, thanks! However, in contrast with library(), require() returns a logical value, which makes it useful in certain situations. I find require() beneficial - in combination with library() - to guarantee the availability of the package of interest. Consider the following example:

if (!require(RCurl)) install.packages('RCurl')
library(RCurl)

yihui yihui 2022-12-16 23:59:01

Yes, I agree with you. This is a good use of require(). We use it too, e.g. https://github.com/rstudio/shiny#installation

Originally posted on 2014-07-28 18:44:24

giscus-bot giscus-bot 2022-12-16 23:59:03
Guest *Aleksandr Blekh* @ 2014-07-28 21:07:47 originally posted:

It's good to know :-). What are the reasons you use :: instead of library()? All I can think of is the intention to save some memory... If Yes, is it significant, even if package doesn't come with own datasets?

yihui yihui 2022-12-16 23:59:05

When I only need one or two functions from a package for a few times, I use pkg::fun. If I need to use a lot of functions a lot of times, I will definitely do library(pkg) to avoid typing pkg:: too many times. Attaching a package should be avoided in general because it "pollutes" the search path and lead to object name clashes potentially. One solution to this is to write a package that imports other packages (i.e. making use of namespaces), instead of attaching them, but I do not think this is a practical solution when we do data analysis on a daily basis.

Originally posted on 2014-07-29 19:23:38

giscus-bot giscus-bot 2022-12-16 23:59:06
Guest *Aleksandr Blekh* @ 2014-07-29 20:33:21 originally posted:

Thank you! Now I understand it a bit better - it's more about namespaces "pollution" than memory conservation.

giscus-bot giscus-bot 2022-12-16 23:58:45
Guest *Marcus Beck* @ 2014-07-28 13:51:33 originally posted:

What about using require to install a package since it returns a logical?

if(require(foo)) {
message('foo loaded correctly')
} else {
install.packages('foo')
}

This would assume that it's okay to install packages w/o consent though...

yihui yihui 2022-12-16 23:59:01

It is an entirely legitimate use of require(). I use it very often, too. In this case, you do not mean "just load the foo package", but "if you can load foo, it is great, otherwise let me install it for you, then load it" (you still need library(foo) after install.packages('foo'), or better, foo::the_function_you_need()).

Originally posted on 2014-07-28 18:41:39

giscus-bot giscus-bot 2022-12-16 23:59:07
Guest *Alex* @ 2014-11-07 05:54:37 originally posted:

If the rest of your code calls functions in foo via foo::the_function_you_need(), why try to load foo at all? Just use if(!("foo" %in% installed.packages())) install.packages("foo")

But if you want to load the package, do what Marcus suggests, followed by library(foo). In that case, require() is the logical choice!

yihui yihui 2022-12-16 23:59:08

You could use requireNamespace() to avoid attaching the package like require() does (again, requireNamespace is an equally bad name as require).

Originally posted on 2014-11-07 19:54:17

giscus-bot giscus-bot 2022-12-16 23:59:10
Guest *bill* @ 2015-01-15 21:29:36 originally posted:

I think I learned this from you. Imagine my surprise when it wasn't mentioned in the post.

yihui yihui 2022-12-16 23:59:15

Now you can use xfun::pkg_attach2('foo').

Originally posted on 2018-07-10 13:55:31

giscus-bot giscus-bot 2022-12-16 23:58:45
Guest *Norm Matloff* @ 2014-08-01 00:19:02 originally posted:

My impression is that somewhere, someone decided that require() is more appropriate within a function for documentation reasons, i.e. to show that this function needs the given package while other functions in the same program don't.

Personally, I think that most dicta in R, and in software development in general, are more follow-like-sheep orthodoxy than real "truths."

giscus-bot giscus-bot 2022-12-16 23:58:46
Guest *aliarsalankazmi* @ 2014-08-28 16:45:06 originally posted:

Thanks!

giscus-bot giscus-bot 2022-12-16 23:58:47
Guest *Charles* @ 2014-11-12 15:20:50 originally posted:

Hi, I have a problem seems. I should remove keep.source from function?

Error in require(MASS, quietly = TRUE, keep.source = FALSE) : unused argument (keep.source = FALSE)

giscus-bot giscus-bot 2022-12-16 23:58:48
Guest *Mike Williamson* @ 2014-12-17 18:17:45 originally posted:

Thank you for this, Yihui! Nice explanation.

You also captured the unfortunate reason why this confusion exists:

"There is one legitimate reason to use require(), though, and that is, 'require is a verb and library is a noun!' I completely agree. require should have been a very nice name to choose for the purpose of loading a package, but unfortunately... you know."

I would go one further and say that "require" means "to be necessary". Therefore, the action that it TRIES and will silently fail with a bool=False does not match the English definition of the word.

I think if library() were actually defined as require() and require() were defined as use() or something similar, these problems wouldn't exist. In fact, I see no problem with

if (!require('foo')) {
stop('The package foo was not installed')
}

precisely because it makes the code easier to read, both for R experts and newbies alike (and more similar to the try-except patterns in other languages). When these poor choices in the language structure are made, useRs make do with what we have.

However, this all pales in comparison to the much larger problem with libraries / packages: name collision by default. :( So, I guess we should pick & choose our battles.

Regardless, your discussion here was excellent! Xie Xie!

giscus-bot giscus-bot 2022-12-16 23:58:49
Guest *100 shades of red* @ 2015-02-12 16:29:48 originally posted:

require is better because library is the reserved keyword in other environments when you happen to use an interconnecting api between r and those

giscus-bot giscus-bot 2022-12-16 23:58:50
Guest *BroVic* @ 2016-05-15 00:37:46 originally posted:

Thank you for this insightful post, Yihui. What I initially thought was one of those quirks in R is actually something noteworthy!

giscus-bot giscus-bot 2022-12-16 23:58:51
Guest *Sree Krishna* @ 2016-06-22 14:09:39 originally posted:

This is enlightening. Thank you!

giscus-bot giscus-bot 2022-12-16 23:58:52
Guest *natus* @ 2017-01-05 21:51:28 originally posted:

library(stringi);detach("package:stringi",unload=TRUE);system.time({for(i in 1:50000){require(stringi);stri_trim("ntoton");stri_trim("ttotot");stri_trim("ntoton")}})
Le chargement a nécessité le package : stringi
utilisateur système écoulé
10.558 0.000 10.572
library(stringi);detach("package:stringi",unload=TRUE);system.time({for(i in 1:50000){library(stringi);stri_trim("ntoton");stri_trim("ttotot");stri_trim("ntoton")}})
utilisateur système écoulé
15.253 0.804 16.100
library(stringi);detach("package:stringi",unload=TRUE);system.time({for(i in 1:50000){stringi::stri_trim("ntoton");stringi::stri_trim("ttotot");stringi::stri_trim("ntoton")}})
utilisateur système écoulé
12.337 0.000 12.353
=> require is faster in such case. (by eg: using the parrallell/foreach package)

yihui yihui 2022-12-16 23:59:11

On one hand, I don't think the possibly saved time really matters. On the other hand, I don't think this is a fair comparison. You should compare require() with library() directly, and only compare them, e.g.

test_require = function() {
  system2('Rscript', c('-e', shQuote('require(stringi)')))
}

test_library = function() {
  system2('Rscript', c('-e', shQuote('library(stringi)')))
}

microbenchmark::microbenchmark(test_require(), test_library())



Unit: milliseconds
           expr      min       lq     mean   median       uq      max neval
 test_require() 153.9646 156.9888 158.7945 158.1176 159.1758 186.2230   100
 test_library() 148.5257 150.2161 152.0214 151.6973 153.2374 165.0811   100

As I said, require() calls library() internally, so in theory it is impossible that require() can be faster than library() (require() = execute library() + other code).

Originally posted on 2017-01-06 22:45:57

giscus-bot giscus-bot 2022-12-16 23:58:53
Guest *Sollano Rabelo Braga* @ 2017-01-26 13:37:51 originally posted:

This is awesome. Thank you!

giscus-bot giscus-bot 2022-12-16 23:58:54
Guest *Noah Fields* @ 2017-05-18 14:48:48 originally posted:

The name "require" sounds like it should do just that--require that the package be loaded or break down. The fact that it does the opposite is counter-intuitive. Perhaps this is the cause of people's confusion (and/or anger). They should have called it attempt().

giscus-bot giscus-bot 2022-12-16 23:58:55
Guest *BroVic* @ 2017-10-19 16:17:33 originally posted:

Great post (I've read this several times). For me, one of the quirkiest things about this topic is what happens when one calls library() without arguments. It's great, but one cannot help but wonder at the disconnect...

yihui yihui 2022-12-16 23:59:12

Glad you came back again. To me, library() without arguments should have been renamed to something like list_packages(). Naming is hard. Naming is hard. :)

Originally posted on 2017-10-19 17:53:14

giscus-bot giscus-bot 2022-12-16 23:58:55
Guest *Liechi Zhang* @ 2018-01-12 08:28:15 originally posted:

Nice post. The behaviors of these functions were of no difference to me before, good to know them. I was also wondering why install.packages() requires "" around the pkg name but library() dose not, it is a surprise for me to find the answer here. This post also reminds me of another thing in R, why install.packages() accepts a vector of pkg names, but library() and require() will throw out an error when I try to load several pkgs at the same time? I know how to do that now using lapply(), just do not understand the logic of design here.

@liechi

yihui yihui 2022-12-16 23:59:13

The reason why library() cannot be vectorized over package is that library() can do other things, and is not only for attaching packages (otherwise it should be easily vectorized), e.g., library(help = "stats") (which is totally weird in my opinion).

I just pushed the functions pkg_attach() and pkg_load() to my xfun package, and you might want to take a look: https://github.com/yihui/xfun/blob/master/R/packages.R

Originally posted on 2018-01-12 16:16:24

giscus-bot giscus-bot 2022-12-16 23:59:14
Guest *Liechi Zhang* @ 2018-01-12 17:19:01 originally posted:

I may not ever need to use 'library(help = "something")' :).
Thanks a lot for adding these interesting functions to your xfun package, it is a more elegant solution than the lapply() method, and way much better than library() five times to start a work. xfun sounds nice.

@liechi

giscus-bot giscus-bot 2022-12-16 23:58:56
Guest *Jose De Jesus Filho* @ 2018-01-12 19:08:57 originally posted:

I have read this post multiple times and still enjoy it.

giscus-bot giscus-bot 2022-12-16 23:58:57
Guest *Ido Hatam* @ 2019-05-15 23:02:53 originally posted:

Guess I'm late to the great post party, but this is a great post. Thanks.

giscus-bot giscus-bot 2022-12-16 23:58:58
Guest *Esty* @ 2019-11-18 19:41:43 originally posted:

VERY nice post, thank you

Sign in to join the discussion

Sign in with GitHub