From murdoch at stats.uwo.ca  Thu Apr  2 16:04:12 2009
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Thu, 02 Apr 2009 10:04:12 -0400
Subject: [Rd] what is the preferred method to create a package
	local	variable?
In-Reply-To: <8ec76080904020641m7058120ckef7dd447a83a644@mail.gmail.com>
References: <8ec76080903310845x3b0a0c2cy22d30cd0799a206e@mail.gmail.com>	<66f3bd910903311235w5421c11ap357ced8a6706f985@mail.gmail.com>	<49D27438.6010806@sciviews.org>
	<8ec76080904020641m7058120ckef7dd447a83a644@mail.gmail.com>
Message-ID: <49D4C5DC.9020607@stats.uwo.ca>

On 4/2/2009 9:41 AM, Whit Armstrong wrote:
> Thanks to everyone for the suggestions.
> 
> The package local environment (per Roger Peng) works well.
> .localstuff <- new.env()
> .localstuff$bbg.db.conn <- dbConnect(...)
> 
> However, there is one thing that I'm confused about.
> 
> Why must the .localstuff variable be an environment?

If a package doesn't have a namespace, then its functions have their 
environment set to the global environment, so they can stomp on user 
things by accident.   I'd say a better solution to this problem is that 
every package should have a namespace, then there isn't the same risk of 
messing with a user's variables.

> 
> I've tried the following, but the variable conn stays null during the
> whole R session.  Despite the database connection succeeding (I can
> see the constructor printing to the console):
> 
> conn <- NULL
> 
> .onAttach <- function(libname, pkgname) {
>     conn <- dbConnect(dbDriver("PostgreSQL"), user="...")
> }

That creates a new local variable called conn.  Use

conn <<- dbConnect ...

to modify the package one. (Assuming you have a namespace; if not, that 
will have different effects depending on whether or not the user has a 
variable named conn.  Yecch.)

Duncan Murdoch

> 
> .onUnload <- function(libpath) {
>     dbDisconnect(conn)
> }
> 
> output from R session:
> 
> [warmstrong at linuxsvr R.packages]$ R
>> library(KLS)
> Loading required package: fts
> Loading required package: RCommodity
> Loading required package: unifiedDBI
> Loading required package: RFincad
> Loading required package: RLIM
> Loading required package: RBoostDateTime
> PostgresConnection::PostgresConnection()
>> KLS:::conn
> NULL
>> x <- get.bbg("EURUSD Curncy")
> Error in get.bbg("EURUSD Curncy") : Database connection not initialized
>> q()
> PostgresConnection::~PostgresConnection()
> [warmstrong at linuxsvr R.packages]$
> 
> 
> Thanks,
> Whit
> 
> 
> 
> 
> 
> 
> On Tue, Mar 31, 2009 at 3:51 PM, Philippe Grosjean
> <phgrosjean at sciviews.org> wrote:
>> The best way is to have those variable hidden in the package's workspace, as
>> explained by Roger Peng.
>>
>> However, if you like to use a mechanism managing an environment specifically
>> dedicated to temporary variables very easily, look at assignTemp() and
>> getTemp() from svMisc package. The advantage is an easier sharing of such
>> variables between different packages (plus the bonus of easy management of
>> default values, overwriting or not of current content if the variable
>> already exists, ...). The temporary environment (TempEnv) is always located
>> in the forelast position just before 'base'.
>>
>> In any cases, avoid using .GlobalEnv and the ugly <<- for that purpose.
>> Best,
>>
>> Philippe Grosjean
>>
>>
>> Roger Peng wrote:
>>>
>>> I usually use environments for this. So, in one of the R files for the
>>> package, just do
>>>
>>> .localstuff <- new.env()
>>>
>>> Then, in functions you can do things like
>>>
>>> .localstuff$bbg.db.conn <- dbConnect(...)
>>>
>>> -roger
>>>
>>> On Tue, Mar 31, 2009 at 11:45 AM, Whit Armstrong
>>> <armstrong.whit at gmail.com> wrote:
>>>>
>>>> for the moment, I'm using:
>>>>
>>>> .onAttach <- function(libname, pkgname) {
>>>>   .bbg.db.conn <<- dbConnect(dbDriver("PostgreSQL"), user="blah","blah")
>>>> }
>>>>
>>>> .onUnload <- function(libpath) {
>>>>   dbDisconnect(.bbg.db.conn)
>>>> }
>>>>
>>>>
>>>> which results in a hidden global variable in the global environment.
>>>>
>>>> I would prefer to make the assignment only in the package namespace.
>>>> I've looked at assignInNamespace, but I can't seem to make it work.
>>>>
>>>> Is there a preferred method for doing this?
>>>>
>>>> When I try adding an assignment directly in the source file, I get the
>>>> "cannot change value of locked binding" error.
>>>>
>>>> What am I missing?
>>>>
>>>> Thanks,
>>>> Whit
>>>>
>>>> ______________________________________________
>>>> 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



[Rd] what is the preferred method to create a package local variable?
Duncan Murdoch