[Rd] Options that are local to the package that sets them
Martin Morgan
mtmorgan at fredhutch.org
Sat Nov 1 02:26:23 CET 2014
On 10/31/2014 05:55 PM, Gábor Csárdi wrote:
> On Fri, Oct 31, 2014 at 8:16 PM, William Dunlap <wdunlap at tibco.com> wrote:
>> You can put the following 3 objects, an environment and 2 functions
>> that access it, in any package that need some package-specific
>> storage (say your pkgB1 and pkgB2).
>> .pkgLocalStorage <- new.env(parent = emptyenv())
>> assignInPkgLocalStorage <- function(name, object) {
>> .pkgLocalStorage[[name]] <- object
>> }
>> getFromPkgLocalStorage <- function(name, object) {
>> .pkgLocalStorage[[name]]
>> }
>> Leave the environment private and export the functions. Then a user can
>> use them as
>> pkgB1::assignInPkgLocalStorage("myPallete", makeAPallete(1,2,3))
>> pkgB2::assignInPkgLocalStorage("myPallete", makeAPallete(5,6,7))
>> pkgB1::getFromPkgLocalStorage("myPallete") # get the 1,2,3 pallete
>
> I am trying to avoid requiring pkgBn to do this kind of magic. I just
> want it to call function(s) from pkgA. But maybe something like this
> would work. In pkgBn:
>
> my_palettes <- pkgA::palette_factory()
>
> and my_palettes is a function or an environment that has the API
> functions to modify my_palettes itself (via closure if it is a
> function), e.g.
>
> my_palettes$add_palette(...)
> my_palettes$get_palette(...)
>
> or if it is a function, then
>
> my_palettes(add(...), ...)
> my_palettes(get(...), ...)
>
> etc.
>
> This would work, right? I'll try it in a minute.
You'll need pkgA to be able to know that pkgB1's invokation is to use pkgB1's
parameters, so coupling state (parameters) with function, i.e., a class with
methods. So a solution is to use an S4 or reference class and generator to
encapsulate state and dispatch to appropriate functions, E.g.,
.Plotter <- setRefClass("Plotter",
fields=list(palette="character"),
methods=list(
update(palette) {
.self$palette <- palette
},
plot=function(...) {
graphics::plot(..., col=.self$palette)
}))
APlotter <- function(palette=c("red", "green", "blue"))
.Plotter(palette=palette)
PkgB1, 2 would then
plt = APlotter()
plt$plot(mpg ~ disp, mtcars)
plt$update(c("blue", "green"))
plt$plot(mpg ~ disp, mtcars)
or
.S4Plotter <- setClass("S4Plotter", representation(palette="character")
S4Plotter <- function(palette=c("red", "blue", "green"))
s4plot <- function(x, ...) graphics::plot(..., col=x at palette))
(make s4plot a generic with method for class S4Plotter to enforce type).
Seems like this interface could be generated automatically in .onLoad() of pkgA,
especially if adopting a naming convention of some sort.
Martin
>
> Gabor
>
>
>> If only one of pkgB1 and pkgB2 is loaded you can leave off the pkgBn::.
>>
>> A package writer can always leave off the pkgBn:: as well.
>>
>> Bill Dunlap
>> TIBCO Software
>> wdunlap tibco.com
>>
>>
>> On Fri, Oct 31, 2014 at 4:34 PM, Gábor Csárdi <csardi.gabor at gmail.com> wrote:
>>> Dear All,
>>>
>>> I am trying to do the following, and could use some hints.
>>>
>>> Suppose I have a package called pkgA. pkgA exposes an API that
>>> includes setting some options, e.g. pkgA works with color palettes,
>>> and the user of the package can define new palettes. pkgA provides an
>>> API to manipulate these palettes, including defining them.
>>>
>>> pkgA is intended to be used in other packages, e.g. in pkgB1 and
>>> pkgB2. Now suppose pkgB1 and pkgB2 both set new palettes using pkgA.
>>> They might set palettes with the same name, of course, they do not
>>> know about each other.
>>>
>>> My question is, is there a straightforward way to implement pkgA's
>>> API, such that pkgB1 and pkgB2 do not interfere? In other words, if
>>> pkgB1 and pkgB2 both define a palette 'foo', but they define it
>>> differently, each should see her own version of it.
>>>
>>> I guess this requires that I put something (a function?) in both
>>> pkgB1's and pkgB2's package namespace. As I see it, this can only
>>> happen when pkgA's API is called from pkgB1 (and pkgB2).
>>>
>>> So at this time I could just walk up the call tree and put the palette
>>> definition in the first environment that is not pkgA's. This looks
>>> somewhat messy, and I am probably missing some caveats.
>>>
>>> Is there a better way? I have a feeling that this is already supported
>>> somehow, I just can't find out how.
>>>
>>> Thanks, Best Regards,
>>> Gabor
>>>
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109
Location: Arnold Building M1 B861
Phone: (206) 667-2793
More information about the R-devel
mailing list