From henrik.bengtsson at ucsf.edu  Wed Oct 14 05:09:34 2015
From: henrik.bengtsson at ucsf.edu (Henrik Bengtsson)
Date: Tue, 13 Oct 2015 20:09:34 -0700
Subject: [Rd] A where() functions that does what exists() does but
 return the environment when object lives?
In-Reply-To: <CABdHhvFmj0xu1s3Ku48phkr91T_JzRQ++BGVEGw2BG1yOjxGqA@mail.gmail.com>
References: <CAFDcVCRR1YwaC=yQXgvgKpoW1HKLPauKYGrU8g9S3q9rAbctLQ@mail.gmail.com>
	<CABdHhvEsKjDQ8qBS_ni8gZNg7JoKtCVhhs7R5h3WaxpVyRdrJA@mail.gmail.com>
	<CABdHhvFmj0xu1s3Ku48phkr91T_JzRQ++BGVEGw2BG1yOjxGqA@mail.gmail.com>
Message-ID: <CAFDcVCT7FKGt65XL_NR-OJpJHEcW19M2uYqHBF1pccXOGW=mYA@mail.gmail.com>

Thanks Uwe and thanks Hadley.  I ended up implementing:

## Emulates R internal findVar1mode() function
## https://svn.r-project.org/R/trunk/src/main/envir.c
where <- function(x, where=-1, envir=if (missing(frame)) { if (where <
0) parent.frame(-where) else as.environment(where) } else
sys.frame(frame), frame, mode="any", inherits=TRUE) {
  tt <- 1
  ## Validate arguments
  stopifnot(is.environment(envir))
  stopifnot(is.character(mode), length(mode) == 1L)
  inherits <- as.logical(inherits)
  stopifnot(inherits %in% c(FALSE, TRUE))

  ## Search
  while (!identical(envir, emptyenv())) {
    if (exists(x, envir=envir, mode=mode, inherits=FALSE)) return(envir)
    if (!inherits) return(NULL)
    envir <- parent.env(envir)
  }

  NULL
}

Here where() provides the same arguments as exists() and get().  It
turns out one needs to tweak the default value for 'envir' argument in
order work the same.

One could argue that where() should always return an environment, i.e.
it should return emptyenv() instead of NULL if the object was not
found.  On the other hand, it's easier to test for is.null(env) than
identical(env, emptyenv()).

/Henrik


On Tue, Oct 13, 2015 at 2:44 PM, Hadley Wickham <h.wickham at gmail.com> wrote:
> On Tue, Oct 13, 2015 at 4:43 PM, Hadley Wickham <h.wickham at gmail.com> wrote:
>> Seems easy enough to write yourself:
>>
>> where <- function(x, env = parent.frame()) {
>>     if (identical(env, emptyenv()))
>>         return(NULL)
>>     if (exists(x, envir = env, inherits = FALSE))
>>         return(env)
>>     where(x, parent.env(env))
>> }
>>
>> sample2 <- base::sample
>> where("sample2")
>> #> <environment: 0x1154d3c28>
>
> And that returns a random environment because I ran it with
> reprex::reprex().  In interactive use it will return <environment:
> R_GlobalEnv>
>
> Hadley
>
> --
> http://had.co.nz/



[Rd] A where() functions that does what exists() does but return the environment when object lives?
Henrik Bengtsson