rticulate / import

An Import Mechanism For R
https://import.rticulate.org
Other
222 stars 14 forks source link

Question regarding S3 methods, dependencies, and functions run inside other functions #73

Closed tony-aw closed 11 months ago

tony-aw commented 1 year ago

Hi, I have a question. I tried the import package to run the following code (just to test out the package):

mgcv <- import::from(mgcv, .all=TRUE, .into = new.env(), .S3=FALSE)
m <- mgcv$gam(
  y ~ s(month, bs="cc") + s(day, bs="cc") + s(points),
  data=d,
  family = binomial,
)
m.summary <- summary(m)
m.vcov <- vcov(m, sandwich = FALSE)
m.coeff <- cbind(coef(m), sqrt(diag(m.vcov)))
m.modmat <- model.matrix(m)
par(mfrow=c(2,2))
plot(m, se = qnorm(0.975), seWithMean = TRUE)

The above code worked perfectly! That's good news, of course. However, I don't fully understand why this works. Specifically, I would like to know the following regarding Python-style importing: 1) inside the formula of the gam() call, I used mgcv's s() function. But notice I just wrote s(), not mgcv$s(). How come the model function still understands s()? (Note: s is not a function defined elsewhere in R, nor did I load the mgcv package, or any package that loads mgcv as a dependency, nor did I load any package that has a similar s function.) 2) How come the S3 methods summary(), vcov(), model.matrix(), and plot(), worked without the mgcv$ prefix and the .gam suffix, despite the fact that I set the .S3 argument to "FALSE"? 3) How are dependencies/required packages taken care of? For example: if you would run require(mgcv), the nlme package would also be loaded as a dependency. However, there is no mgcv$nlme() function available, when I ran the above code (nlme is one of the functions of the nlme package). So how are the dependencies incorporated? 4) Lastly (I almost forget), what is the difference between using the import package and simply running mgcv <- loadNamespace("mgcv")?

I did check your vignette en read-me files before asking the above questions, but I still don't have a fully complete picture of the import package functionality with respect to the above topics. Hence the questions above. I hope you have the time to answer my questions.

Thank you in advance for your time and patience.

torfason commented 1 year ago

These are pretty big questions having to do with how R evaluates code in different environments and what is visible from where. The best I can offer is to read Advanced R (https://adv-r.hadley.nz/) together with the source code. Not saying they are not good questions, just that answering them satisfactorily would take some work.

I, for one, am definitely not able to answer them off the top of my head, but would need to refer to Advanced R and the source code myself ...

  1. Well, that one I will answer, to an extent. I believe the difference is pretty similar to the difference between library(magrittr) and import::from(magrittr, .all=TRUE). The import package reimplements a lot of the stuff that base R does to load packages and namespaces, in order to add features (importing scripts, and allowing the user to specify which objects are imported, were the main desired features) that were unavailable in base R at the time of writing. More and more of the functionality that motivated import is being added to base R, so probably the areas of overlap are going to increase.

I'll probably close this issue soon, because I'd like to keep the issue tracker for actual issues, but feel free to reopen the question under the discussion tab, where it could live on for longer. If you do, it would be great if you define d so that the example that you posted is reproducible for anyone who wants to check out the questions.

J-Moravec commented 1 year ago

@torfason

The import package reimplements a lot of the stuff that base R does to load packages and namespaces,

This is completely unrelated, but is there a bigger support for namespaces in R? Last time I was trying to read about it, it was kind-of only partially done and while there were some ideas about having multi-namespace packages (or namespaces shared between packages), it was never implemented.

So the question is: is there enough support for namespaces so that we could have something of the form:

import::to(pseudopkg, "myscript.src")

pseudopkg::myfun(...)
torfason commented 11 months ago

Most of this thread is a general discussion, and although the comment from @J-Moravec could be construed as a feature request, I myself do not know how to proceed with that.It has seemed to me that in general, the best way forward in complex situations regarding environment is to use import::here(), although I'm always happy when things work for people :-)

The v.1.3.1 release is now out, and I'm doing a bit of a cleanup, so I'm closing this issue now. If there is a specific solution that you would propose, feel free to reopen the issue. Alternatively, it could be migrated to a discussion.