From simon.urbanek at r-project.org  Fri Jul 26 17:17:55 2013
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Fri, 26 Jul 2013 11:17:55 -0400
Subject: [Rd] How to best implement package options?
In-Reply-To: <s3s7ggda0cu.fsf@slagelg.uio.no>
References: <s3s7ggda0cu.fsf@slagelg.uio.no>
Message-ID: <74F6456C-3BFE-4D23-84EE-8B7D09C42B07@r-project.org>


On Jul 26, 2013, at 9:59 AM, Bj?rn-Helge Mevik wrote:

> Dear developeRs,
> 
> I have a package, pls, that implements package options.  The users are
> supposed to use a function pls.options() to manipulate them.
> 
> If a user changes the options, they are stored in .GlobalEnv.  I was
> recently informed that this is against current CRAN submission policies,
> so I need to change that.
> 
> 
> I have looked at several different packages that implement package
> options, and found that:
> 
> 
> 1) Many packages simply use the global R options, setting default
>  options with base::options() inside either .onLoad() or .onAttach().
>  Users then are supposed to use base::options() etc. for manipulating
>  the options.
> 
>  This has the advantages that users can use the standard options
>  interface, and the package authors don't need to "reinvent the wheel".
> 
>  One disadvantage is the possibility for name collisions between
>  package options.  Some packages try to minimise that risk by prefixing
>  all options with the package name.
> 
> 
> 2) Some packages implement their own version of options() (like
>  pls.options()), and store a list of options in the package name space.
> 
>  This avoids any name collisions, but users have to relate to several
>  options interfaces (the ones I've seen work mostly the same as the
>  standard options(), though).
> 
>  AFAIK, this solution neccessitates calling unlockBinding() on the
>  option list, or using assignInMyNamespace() to update it.
> 

That is certainly not a good way. If you have the urge to use unlockBinding() or assign*Namespace() then think again as your design is likely bad. If you want to store package-local information, simply create an environment in your package - it's this simple:

.myenv <- new.env(TRUE, emptyenv())

The environment is independent of the namespace (you don't export it) and thus you don't need any ugly hacks. The code in your package can manipulate it directly, while the user cannot easily mess with it.


> 3) Finally, I've found one package ('pkgmaker') that implements a
>  general mechanism that can be used by other packages to create package
>  options.  The mechanism creates options()-like functions in the
>  package's name space, and the optins are either stored as a single
>  option in base:::.Options, or in the created function's enclosure.
> 
>  Again, users need to relate to separate options interfaces, but the
>  package authors don't have to "reinvent the wheel".
> 
> 
> What is considered "best practice" for implementing package options?
> Any of the above, or something different?
> 

Personally, I hate when packages use their own option management system because it leads to vastly inconsistent behavior, so I prefer using the options() as that is transparent and well defined. But that is just my personal opinion.

Cheers,
Simon


> 
> -- 
> RegaRds,
> Bj?rn-Helge Mevik
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] How to best implement package options?
Simon Urbanek