Marc Girondot
2017-Feb-02 14:30 UTC
[R] Function that works within a package and not when copied in global environment. Why?
Dear experts, In the package nlWaldTest, there is an hidden function : .smartsub I can use it, for example: > getFromNamespace(".smartsub", ns="nlWaldTest")(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") [1] "essai(b[1], b[2], b[1])" Now I try to create this function in my global environment: smartsub <- getFromNamespace(".smartsub", ns="nlWaldTest") It works also: > smartsub(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") [1] "essai(b[1], b[2], b[1])" But if I create the function manually: > smartsub2 <- function (pat, repl, x) { args <- lapply(as.list(match.call())[-1L], eval, parent.frame()) names <- if (is.null(names(args))) character(length(args)) else names(args) dovec <- names %in% vectorize.args do.call("mapply", c(FUN = FUN, args[dovec], MoreArgs = list(args[!dovec]), SIMPLIFY = SIMPLIFY, USE.NAMES = USE.NAMES)) } > smartsub2(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") Error in names %in% vectorize.args : objet 'vectorize.args' introuvable It fails because vectorize.args is unknown Indeed smartsub2 is different from smartsub. > identical(smartsub, smartsub2) [1] FALSE 1/ Why are they different? They are just a copy of each other. 2/ Second question, vectorize.args is indeed not defined before to be used in the function. Why no error is produced in original function? Thanks a lot Marc -- __________________________________________________________ Marc Girondot, Pr Laboratoire Ecologie, Syst?matique et Evolution Equipe de Conservation des Populations et des Communaut?s CNRS, AgroParisTech et Universit? Paris-Sud 11 , UMR 8079 B?timent 362 91405 Orsay Cedex, France Tel: 33 1 (0)1.69.15.72.30 Fax: 33 1 (0)1.69.15.73.53 e-mail: marc.girondot at u-psud.fr Web: http://www.ese.u-psud.fr/epc/conservation/Marc.html Skype: girondot
Bert Gunter
2017-Feb-02 16:01 UTC
[R] Function that works within a package and not when copied in global environment. Why?
1. No they're not. e.g.> f <- function() NULL > g <- function()NULL> identical(f,g)[1] FALSE> str(f)function () - attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 6 1 20 6 20 1 1 .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x1026578d0>> str(g)function () - attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 6 1 19 6 19 1 1 .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x102613028>> h <- f > identical(f,h)[1] TRUE identical() is very fussy about whether t=2 objects are the same; they must be identical in all respects, including attributes, classes, etc. attached to them. The namespace object has different attributes attached to it than the one you created. 2. You need to review how namespaces work. From the "Writing R extensions" manual: "The namespace controls the search strategy for variables used by **functions in the package**. If not found locally, R searches the package namespace first, then the imports, then the base namespace and then the normal search path." So if vectorize.args() is among the package functions, it will be found by package functions but not by those you write unless specifically qualified by :: or ::: depending on whether it is exported. Cheers, Bert Bert Gunter "The trouble with having an open mind is that people keep coming along and sticking things into it." -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) On Thu, Feb 2, 2017 at 6:30 AM, Marc Girondot via R-help <r-help at r-project.org> wrote:> Dear experts, > > In the package nlWaldTest, there is an hidden function : .smartsub > > I can use it, for example: > >> getFromNamespace(".smartsub", ns="nlWaldTest")(pat="x", repl="b" , > x="essai(b[1], b[2], x[1])") > [1] "essai(b[1], b[2], b[1])" > > Now I try to create this function in my global environment: > smartsub <- getFromNamespace(".smartsub", ns="nlWaldTest") > > It works also: >> smartsub(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") > [1] "essai(b[1], b[2], b[1])" > > But if I create the function manually: >> smartsub2 <- function (pat, repl, x) > { > args <- lapply(as.list(match.call())[-1L], eval, parent.frame()) > names <- if (is.null(names(args))) > character(length(args)) > else names(args) > dovec <- names %in% vectorize.args > do.call("mapply", c(FUN = FUN, args[dovec], MoreArgs > list(args[!dovec]), > SIMPLIFY = SIMPLIFY, USE.NAMES = USE.NAMES)) > } >> smartsub2(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") > Error in names %in% vectorize.args : objet 'vectorize.args' introuvable > > It fails because vectorize.args is unknown > > Indeed smartsub2 is different from smartsub. >> identical(smartsub, smartsub2) > [1] FALSE > > 1/ Why are they different? They are just a copy of each other. > > 2/ Second question, vectorize.args is indeed not defined before to be used > in the function. Why no error is produced in original function? > > Thanks a lot > > Marc > > > -- > > __________________________________________________________ > Marc Girondot, Pr > > Laboratoire Ecologie, Syst?matique et Evolution > Equipe de Conservation des Populations et des Communaut?s > CNRS, AgroParisTech et Universit? Paris-Sud 11 , UMR 8079 > B?timent 362 > 91405 Orsay Cedex, France > > Tel: 33 1 (0)1.69.15.72.30 Fax: 33 1 (0)1.69.15.73.53 > e-mail: marc.girondot at u-psud.fr > Web: http://www.ese.u-psud.fr/epc/conservation/Marc.html > Skype: girondot > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Marc Girondot
2017-Feb-02 16:34 UTC
[R] Function that works within a package and not when copied in global environment. Why?
Thanks Bert for the explanation about identical. For the vectorize.args, note that vectorize.args is not a function but an variable that is unknown in the namespace nlWaldTest. > nlWaldTest::vectorize.args Erreur : 'vectorize.args' n'est pas un objet export? depuis 'namespace:nlWaldTest' Furthermore, if the function is created from a copy of the original one: smartsub <- getFromNamespace(".smartsub", ns="nlWaldTest") or if it is created manually: by copy-paste of the code: smartsub2 <- function (pat, repl, x) { args <- lapply(as.list(match.call())[-1L], eval, parent.frame()) names <- if (is.null(names(args))) character(length(args)) else names(args) dovec <- names %in% vectorize.args do.call("mapply", c(FUN = FUN, args[dovec], MoreArgs = list(args[!dovec]), SIMPLIFY = SIMPLIFY, USE.NAMES = USE.NAMES)) } Both are defined in the global env, but the first one works and not the second one. I am surprised and don't understand how it is possible. Sincerely Marc Girondot> 2. You need to review how namespaces work. From the "Writing R > extensions" manual: > > "The namespace controls the search strategy for variables used by > **functions in the package**. If not found locally, R searches the > package namespace first, then the imports, then the base namespace and > then the normal search path." > > So if vectorize.args() is among the package functions, it will be > found by package functions but not by those you write unless > specifically qualified by :: or ::: depending on whether it is > exported. > > Cheers, > Bert > > > > Bert Gunter > > "The trouble with having an open mind is that people keep coming along > and sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Thu, Feb 2, 2017 at 6:30 AM, Marc Girondot via R-help > <r-help at r-project.org> wrote: >> Dear experts, >> >> In the package nlWaldTest, there is an hidden function : .smartsub >> >> I can use it, for example: >> >>> getFromNamespace(".smartsub", ns="nlWaldTest")(pat="x", repl="b" , >> x="essai(b[1], b[2], x[1])") >> [1] "essai(b[1], b[2], b[1])" >> >> Now I try to create this function in my global environment: >> smartsub <- getFromNamespace(".smartsub", ns="nlWaldTest") >> >> It works also: >>> smartsub(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") >> [1] "essai(b[1], b[2], b[1])" >> >> But if I create the function manually: >>> smartsub2 <- function (pat, repl, x) >> { >> args <- lapply(as.list(match.call())[-1L], eval, parent.frame()) >> names <- if (is.null(names(args))) >> character(length(args)) >> else names(args) >> dovec <- names %in% vectorize.args >> do.call("mapply", c(FUN = FUN, args[dovec], MoreArgs >> list(args[!dovec]), >> SIMPLIFY = SIMPLIFY, USE.NAMES = USE.NAMES)) >> } >>> smartsub2(pat="x", repl="b" , x="essai(b[1], b[2], x[1])") >> Error in names %in% vectorize.args : objet 'vectorize.args' introuvable >> >> It fails because vectorize.args is unknown >> >> Indeed smartsub2 is different from smartsub. >>> identical(smartsub, smartsub2) >> [1] FALSE >> >> 1/ Why are they different? They are just a copy of each other. >> >> 2/ Second question, vectorize.args is indeed not defined before to be used >> in the function. Why no error is produced in original function? >> >> Thanks a lot >> >> Marc >> >> >> -- >> >> __________________________________________________________ >> Marc Girondot, Pr >> >> Laboratoire Ecologie, Syst?matique et Evolution >> Equipe de Conservation des Populations et des Communaut?s >> CNRS, AgroParisTech et Universit? Paris-Sud 11 , UMR 8079 >> B?timent 362 >> 91405 Orsay Cedex, France >> >> Tel: 33 1 (0)1.69.15.72.30 Fax: 33 1 (0)1.69.15.73.53 >> e-mail: marc.girondot at u-psud.fr >> Web: http://www.ese.u-psud.fr/epc/conservation/Marc.html >> Skype: girondot >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code.