From mtmorgan at fhcrc.org  Wed Jan 14 05:07:35 2009
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Tue, 13 Jan 2009 20:07:35 -0800
Subject: [Rd] particulars of importing/loading libraries
In-Reply-To: <E66844FE-E31E-45F4-8753-72445204E7A6@r-project.org> (Simon
	Urbanek's message of "Tue, 13 Jan 2009 20:50:54 -0500")
References: <1A68FCB28DE72F4BA3B967E6506CCE43047DF583@mildnpexmb01.maninvestments.ad.man.com>
	<E66844FE-E31E-45F4-8753-72445204E7A6@r-project.org>
Message-ID: <6ph63kibke0.fsf@gopher4.fhcrc.org>

Simon Urbanek <simon.urbanek at r-project.org> writes:

> Oleg,
>
> On Jan 13, 2009, at 11:00 , Sklyar, Oleg (London) wrote:
>
>> Dear List:
>>
>> Sorry for posting maybe a trivial question, but I have a basic
>> understanding problem. If I have say pack1 and pack2, two R packages,
>> and pack2 depends on and imports pack1 fully (as in the code below),
>> is
>> there a way to make all the functionality of pack1 available for the
>> global and other environments (not only for the functions called from
>> withing pack2) by loading pack2 only? I thought if pack2 depends on
>> and
>> imports pack1 and essentially reexports everything, one should get the
>> full functionality simply by loading pack2. This does not seem to be
>> the
>> case or I am missing something trivial in my NAMESPACE/DESCRIPTION
>> files?
>>
>> If this is documented in Writing R Extensions, I would be thankful
>> for a
>> page number and maybe a quick fix in my example below as so far I have
>> not been able to find a clear explanation.
>>
>> The problem can be illustrated by the following simple example (this
>> is
>> a simple code for 2 packages, pack1 and pack2; plus an example).
>>
>
> if you bothered to use R CMD check you would find your bug right away:
> * checking package dependencies ... ERROR
> Namespace dependencies not required:
>    pack1
>
> You simply forgot to add pack1 to the Depends: line - that's all. Once
> you fix that, you'll see what happens:

Imports: rather than Depends: seems like the norm -- the package then
controls its search path, rather than relying on the search path
constructed by the user, and avoids cluttering the user name space and
search path with unnecessary symbols. This would be especially true
for an infrastructure package with many symbols (e.g., RGtk2?) that
might well be irrelevant to an end user.

With Oleg's example, using Imports: allows the package to pass R CMD
check but results in the same error

> packageDescription("pack2")[c("Imports", "Depends")]
$Imports
[1] "pack1"

$Depends
[1] "R (>= 2.7.1), methods"

> as.POSIXct(pack1::testPosixVal)
Error in as.POSIXct.default(pack1::testPosixVal) : 
  do not know how to convert 'pack1::testPosixVal' to class "POSIXlt"

This can be remedied by adding exports(as.POSIXct) to the NAMESPACE
file of pack2.

I said above that the Imports: gives the package control of its search
path. This is true for regular symbols

> testPosixValue = "not a posix value"
> testPosix() # finds pack1's testPosixValue
[1] "2009-01-14 03:55:25 UTC"
[1] "POSIXt"  "POSIXct"
[1] "2009-01-14 03:55:25 UTC"

so one might hope that if pack2 Imports: pack1, pack2 would always get
pack1's as.POSIXct methods. Alas, the user writing a method

setMethod("as.POSIXct", signature(x="posixTime"),
          function(x, tz, ...) stop('oops'))

clobers pack2's efforts

> testPosix()
Error in as.POSIXct(testPosixVal) : oops

This occurs even when pack2 does not export as.POSIXct (niether method
nor generic), and would seem to be an unfortunate interaction between
methods and name spaces.

Martin

>  > library(pack2)
> Loading required package: pack1
>  > as.POSIXct(pack1::testPosixVal)
> [1] "2009-01-14 01:38:08 UTC"
>
> Cheers,
> S
>
>
>> Thank you for your replies.
>>
>> Dr Oleg Sklyar
>> Research Technologist
>> AHL / Man Investments Ltd
>> +44 (0)20 7144 3107
>> osklyar at maninvestments.com
>>
>> --- pack1: DESCRIPTION ------
>> Package: pack1
>> Version: 0.0.1
>> Date: 12 Jan 2009
>> Title: pack1 to test S3/S4 methods compatibility
>> Author:  Oleg Sklyar
>> Depends: R (>= 2.7.1), methods
>> Maintainer: Oleg Sklyar <osklyar at maninvestments.com>
>> Description: pack1
>> LazyLoad: yes
>> License: Proprietary
>> URL: http://www.maninvestments.com
>> LazyLoad: no
>>
>> --- pack1: NAMESPACE ------
>> import(methods)
>> exportPattern("^[^\\.]")
>> exportClasses(posixTime)
>> exportMethods(as.POSIXct)
>>
>> --- pack1: posix.R ------
>> setClass("posixTime", "numeric")
>>
>> setGeneric("as.POSIXct")
>> setMethod("as.POSIXct", signature(x="posixTime"),
>>    function(x, tz) {
>>        z = x at .Data
>>        attr(z,"class") = c("POSIXt", "POSIXct")
>>        attr(z,"tzone") = "UTC"
>>        z
>>    }
>> )
>>
>> testPosixVal = new("posixTime", as.numeric(Sys.time()))
>>
>> --- pack2: DESCRIPTION
>> Package: pack2
>> Version: 0.0.1
>> Date: 12 Jan 2009
>> Title: pack2 to test S3/S4 methods compatibility
>> Author:  Oleg Sklyar
>> Depends: R (>= 2.7.1), methods
>> Maintainer: Oleg Sklyar <osklyar at maninvestments.com>
>> Description: pack2
>> LazyLoad: yes
>> License: Proprietary
>> URL: http://www.maninvestments.com
>> LazyLoad: no
>>
>> --- pack2: NAMESPACE ------
>> import(pack1)
>> exportPattern("^[^\\.]")
>>
>> --- pack2: posix.R ------
>> testPosix = function() {
>>    z = as.POSIXct(testPosixVal)
>>    print(z)
>>    print(class(z))
>>    z
>> }
>>
>> ------ test code to run from global env, showing problems -------
>> require(pack2)
>>
>> ## use as.POSIXct imported into pack2 from pack1 to do the
>> conversion in
>> the fun
>> testPosix()
>> #~ [1] "2009-01-13 15:29:50 UTC"
>> #~ [1] "POSIXt"  "POSIXct"
>> #~ [1] "2009-01-13 15:29:50 UTC"
>>
>> ## now try using it directly from the global env (pack1 was not
>> explicitly loaded)
>> as.POSIXct(pack1::testPosixVal)
>> #~ Error in as.POSIXct.default(pack1::testPosixVal) :
>> #~  do not know how to convert 'pack1::testPosixVal' to class
>> "POSIXlt"
>>
>> ## now require pack1 explicitly and try again
>> require(pack1)
>> as.POSIXct(pack1::testPosixVal)
>> #~ [1] "2009-01-13 15:29:50 UTC"
>>
>>
>> **********************************************************************
>> Please consider the environment before printing this email or its
>> attachments.
>> The contents of this email are for the named addressees
>> ...{{dropped: 19}}
>>
>> ______________________________________________
>> 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

-- 
Martin Morgan
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109

Location: Arnold Building M2 B169
Phone: (206) 667-2793



[Rd] particulars of importing/loading libraries
Martin Morgan