Skip to content

Defining/Checking constants in packages

6 messages · Giovanni Petris, Deepayan Sarkar, Henrik Bengtsson +3 more

#
In a package I am writing I need to use the constant pi (3.14..., that
is) which is already defined in R. However, how can I make sure the
user has not changed its value before loading the package? 
If this happened, is a reference to `pi' in the package going to use
the user-defined value or the value defined in base?
I thought I could solve the issue by including the following line in
my package
   pi <- get("pi", pos=grep("package:base",search()))
but then when I load the package R warns me about masking issues. 
What is the recommended way of dealing with this issue?

Thank you in advance,
Giovanni
#
Although namespaces are not fully implemented yet, the base namespace does 
work in R 1.6.x. e.g.,
[1] 90
[1] 3.141593

(Of course, there might be other ways as well.)
On Wednesday 20 November 2002 03:39 pm, Giovanni Petris wrote:
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
If you add

# Allows conflicts. For more information, see library() and
# conflicts() in [R] base.
.conflicts.OK <- TRUE 

to your package you will not get a warning with masking objects when
your package is loaded. I normally include this line in a file named
zzz.R in which one normally also add functions as .First.lib() etc.

Otherwise there are no way to specify (final) constants in R. The new
support for name spacing, as Deepayan Sarkar mention in the other email,
will solve some of these problems. However, a common coding convention
between programmers could also prevent a lot of these problems. For
instance, using the widely used naming convention that constants have
only captial letters, e.g. PI, and (changing) variables not, would
minimize the risk for redefinition of its value. Of course, it could
still be that different programmers defines PI differently. For *my own
and my collegues* purposes, I am trying to define such a coding
convention for minimizing mishaps like the one you describe. It can be
found on http://www.maths.lth.se/help/R/RCC/, but note that is under
construction(!).

Best wishes

Henrik Bengtsson
Lund University
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
On Wed, 20 Nov 2002, Deepayan Sarkar wrote:

            
[1] 3.141593

is equivalent and works in all versions of R.  Just use it, rather than
assigning the value.

  
    
#
On Thu, 21 Nov 2002 ripley at stats.ox.ac.uk wrote:

            
Brian probably meant to use envir=NULL or pos="package:base".  Using
envir=.GlobalEnv is equivalent to just

	> pi
	[1] 3.141593

which is subject to masking by loaded packages and assignments to
.GlobalEnv.  base::pi is equivalent to

	> get("pi", pos="package:base")
	[1] 3.141593

or

	>  get("pi", envir=NULL)
	[1] 3.141593

To expand on Brian's point, even if you did assign a value to pi in
your package that would only prevent masking by packages loaded prior
to yours.  Your functions are defined in the global environment, so
their globals are looked up in the global environment, the search
list, and then base.  If a package that does pi<-3 is loaded after
yours or if the user makes such an assignment at top level, then the
value your package gets for pi is 3.  Using base::pi in the current R
or get("pi", pos="package:base") is safer.

Within a month the development version of R should have a name space
mechanism that allows a package to explicitly specify which other
packages it uses (imports); functions in a package using this
mechanism will be defined in an environment that searches the package
itself, explicit imports (if any), and then base before .GlobalEnv and
attached packages.  This insures that attaching packages and assigning
into .GlobalEnv will not be able to mask definitions used in your
code.

As of 1.6 the base package is already defined in a name space, so any
functions in base that use pi will see the definition in base;
redefining pi in a loaded package or at top level cannot affect these
functions.

luke
#
This:
Doesn't seem to work for me:

 > get("pi", pos="package:base")
[1] 0

Now, that might be because I've redefined 'get':

 > get
function(x,pos=y){0}

:)

  So maybe if I am scared someone has redefined 'pi', I should also be 
paranoid about them redefining 'get'. However, I cant use:

get("get", pos="package:base")

  because my 'get' is already poisoned. So how can I reliably get the 
'get' in package:base:

 > base::get("pi",pos="package:base")
[1] 3.141593

?

Baz

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._