Henrik Bengtsson
2015-Jan-26 20:41 UTC
[Rd] Inspect a "delayed" assigned whose value throws an error?
On Mon, Jan 26, 2015 at 12:24 PM, Hadley Wickham <h.wickham at gmail.com> wrote:> If it was any other environment than the global, you could use substitute: > > e <- new.env() > delayedAssign("foo", stop("Hey!"), assign.env = e) > substitute(foo, e) > > delayedAssign("foo", stop("Hey!")) > substitute(foo)Hmm... interesting and odd. Unfortunately, this doesn't seem to help for reaching into the namespace of hgu133a.db and inspecting 'hgu133aPFAM', e.g.> library("hgu133a.db")> substitute(hgu133aPFAM, env=ns)Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM or PROSITE accessions.> evalq(substitute(hgu133aPFAM), envir=ns)Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM or PROSITE accessions.> evalq(substitute(hgu133aPFAM, env=ns), envir=ns)Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM or PROSITE accessions. Thanks, Henrik> > Hadley > > On Mon, Jan 26, 2015 at 12:53 PM, Henrik Bengtsson <hb at biostat.ucsf.edu> wrote: >> Hi, I got an interesting programming challenge: >> >> How do you inspect an object which is assigned via delayedAssign() and >> that throws an error as soon as it is "touched" (=the value is >> evaluated)? Is it possible? >> >> >> MINIMAL EXAMPLE: >> >> $ R --vanilla >>> delayedAssign("foo", stop("Hey!")) >> >> (If you find this minimal example silly/obvious, please skip down to >> the real example at the end) >> >>> foo >> Error: Hey! >> >>> str(foo) >> Error in str(foo) : Hey! >> In addition: Warning message: >> In str(foo) : restarting interrupted promise evaluation >> >>> mode(foo) >> Error in mode(foo) : Hey! >> In addition: Warning message: >> In mode(foo) : restarting interrupted promise evaluation >> >>> .Internal(inspect(foo)) >> Error: Hey! >> In addition: Warning message: >> restarting interrupted promise evaluation >> >>> traceback() >> 1: stop("Hey!") >> >> Is there anyway I can inspect this object using the R API without >> evaluating the value in the delayed assignment? Is it possible to >> test if this is a delayed assigned or not? >> >> >> BACKGROUND: >> The background to this is where I have a function in the R.oo package >> that scans namespaces for functions with a certain class attribute. >> For this I use is.function() and inherits() to inspect each object. >> An aroma.affymetrix user reported on a problem that boiled down to the >> following: >> >> # source("http://bioconductor.org/biocLite.R"); biocLite("hgu133a.db") >>> library("hgu133a.db") >>> is.function(hgu133aPFAM) >> Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM >> or PROSITE accessions. >>> .Internal(inspect(hgu133aPFAM)) >> >>> traceback() >> 3: stop(paste(msg, collapse = ""), call. = FALSE, domain = NA) >> 2: .Defunct(msg = msg) >> 1: (function () >> { >> if (grepl("PFAM", x)) { >> bimapName <- paste0(prefix, "PFAM") >> } >> else { >> bimapName <- paste0(prefix, "PROSITE") >> } >> x <- dc[[bimapName]] >> msg = wmsg(paste0(bimapName, " is defunct. ", "Please use select() if you >> need access to PFAM or PROSITE accessions. \n")) >> if (interactive()) { >> .Defunct(msg = msg) >> } >> })() >> >> My immediate solution is to perform those tests using tryCatch(), but >> this is interesting, because this function is such that the error is >> only thrown in interactive() sessions, i.e. the following works: >> >> $ Rscript -e "hgu133a.db::hgu133aPFAM" >> [...] >> NULL >> >> This is probably also why none of my aroma.affymetrix system tests >> caught this. Without tracing the source code behind, which seems >> quite nested, the above is why I believe the assignment is "delayed"; >> traceback() shows a body source code, the object evaluates to >> different things depending on interactive(). >> >> /Henrik >> >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > > > > -- > http://had.co.nz/
Martin Maechler
2015-Jan-27 14:56 UTC
[Rd] Inspect a "delayed" assigned whose value throws an error?
>>>>> Henrik Bengtsson <hb at biostat.ucsf.edu> >>>>> on Mon, 26 Jan 2015 12:41:48 -0800 writes:> On Mon, Jan 26, 2015 at 12:24 PM, Hadley Wickham <h.wickham at gmail.com> wrote: >> If it was any other environment than the global, you could use substitute: >> >> e <- new.env() >> delayedAssign("foo", stop("Hey!"), assign.env = e) >> substitute(foo, e) >> >> delayedAssign("foo", stop("Hey!")) >> substitute(foo) > Hmm... interesting and odd. > Unfortunately, this doesn't seem to help for reaching into the > namespace of hgu133a.db and inspecting 'hgu133aPFAM', e.g. >> library("hgu133a.db") >> substitute(hgu133aPFAM, env=ns) > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > or PROSITE accessions. >> evalq(substitute(hgu133aPFAM), envir=ns) > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > or PROSITE accessions. >> evalq(substitute(hgu133aPFAM, env=ns), envir=ns) > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > or PROSITE accessions. this *is* interesting.. Note that shortly after delayedAssign() was introduced into R, we had R : Copyright 2005, The R Foundation for Statistical Computing Version 2.2.1 (2005-12-20 r36812) ISBN 3-900051-07-0 ............ > delayedAssign("x", pi^2) ; substitute(x) pi^2 > so it also worked with the globalenv; but that feature already disappeared with R : Copyright 2006, The R Foundation for Statistical Computing Version 2.3.0 (2006-04-24) Almost surely as an inadvertent side effect of something else. ----------------------------------- --> Quiz (even though it's not Friday) : The help page for delayedAssign() contains a somewhat more sophisticated example of 'promise's, and BTW an example that worked also in *much* earlier version of R, probably in all versions of R {I checked R 1.0.1, probably the oldest still running on my current Linux desktop} : e <- (function(x, y = 1, z) environment())(1+2, "y", {cat(" HO! "); pi+2}) which gives an environment full of promises Now, the following also works alread in R 1.0.1 :> gete <- function(e)lapply(lapply(ls(env=e), as.name), function(n) eval(substitute(substitute(X, e), list(X=n))))> gete(e)[[1]] 1 + 2 [[2]] [1] "y" [[3]] { cat(" HO! ") pi + 2 }>In newer versions of R, you can use 'ls(e)' instead of 'ls(env=e)', and we have bquote() to make it a tad shorter: gete2 <- function(e) lapply(lapply(ls(e), as.name), function(n) eval(bquote(substitute(.(n), e)))) Apart from that (and from not using spaces and from silly things such as 'L = lapply', and using L), can anyone find a shorter (or "nicer") way to achieve the same as gete(), or gete2(), i.e., return a list with the promise expressions and not evaluating e ? You are not allowed to use 'x', 'y', and 'z' explicitly of course, because here, gete0 <- function(e) list(substitute(x,e), substitute(y,e), substitute(z,e)) would be slightly shorter. Martin
Hadley Wickham
2015-Jan-27 15:03 UTC
[Rd] Inspect a "delayed" assigned whose value throws an error?
On Tue, Jan 27, 2015 at 8:56 AM, Martin Maechler <maechler at lynne.stat.math.ethz.ch> wrote:>>>>>> Henrik Bengtsson <hb at biostat.ucsf.edu> >>>>>> on Mon, 26 Jan 2015 12:41:48 -0800 writes: > > > On Mon, Jan 26, 2015 at 12:24 PM, Hadley Wickham <h.wickham at gmail.com> wrote: > >> If it was any other environment than the global, you could use substitute: > >> > >> e <- new.env() > >> delayedAssign("foo", stop("Hey!"), assign.env = e) > >> substitute(foo, e) > >> > >> delayedAssign("foo", stop("Hey!")) > >> substitute(foo) > > > Hmm... interesting and odd. > > > Unfortunately, this doesn't seem to help for reaching into the > > namespace of hgu133a.db and inspecting 'hgu133aPFAM', e.g. > > >> library("hgu133a.db") > > >> substitute(hgu133aPFAM, env=ns) > > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > > or PROSITE accessions. > > >> evalq(substitute(hgu133aPFAM), envir=ns) > > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > > or PROSITE accessions. > > >> evalq(substitute(hgu133aPFAM, env=ns), envir=ns) > > Error: hgu133aPFAM is defunct. Please use select() if you need access to PFAM > > or PROSITE accessions. > > this *is* interesting.. > > Note that shortly after delayedAssign() was introduced into R, > we had > > R : Copyright 2005, The R Foundation for Statistical Computing > Version 2.2.1 (2005-12-20 r36812) > ISBN 3-900051-07-0 > > ............ > > > delayedAssign("x", pi^2) ; substitute(x) > pi^2 > > > > so it also worked with the globalenv; but that feature already > disappeared with > > R : Copyright 2006, The R Foundation for Statistical Computing > Version 2.3.0 (2006-04-24) > > Almost surely as an inadvertent side effect of something else.The substitute docs have: "If it is an ordinary variable, its value is substituted, unless env is .GlobalEnv in which case the symbol is left unchanged." So it's definitely a deliberate change. This commit looks related: https://github.com/wch/r-source/commit/182d197094f8fcecf6ec8f14bfc7c69a02ac251d. There Duncan commented "For historical reasons, don't substitute in R_GlobalEnv", which suggests that the behaviour you see in 2.2.1 might have been a bug. Hadley -- http://had.co.nz/
Possibly Parallel Threads
- Inspect a "delayed" assigned whose value throws an error?
- Inspect a "delayed" assigned whose value throws an error?
- Inspect a "delayed" assigned whose value throws an error?
- DO NOT REPLY [Bug 5963] New: rsync fails with errors that make no sense...
- combine 3 affybatches