On Fri, May 17, 2013 at 2:47 AM, Duncan Murdoch <murdoch.duncan@gmail.com>wrote:

> On 13-05-16 11:17 PM, Peter Meilstrup wrote:
>
>> On Thu, May 16, 2013 at 6:06 AM, McGehee, Robert <
>> Robert.McGehee@geodecapital.**com <Robert.McGehee@geodecapital.com>>
>> wrote:
>>
>>  Duncan, Thank you for the clarification on how delayedAssign works.
>>> Should
>>> R-level interfaces to promise objects ever become available, I expect
>>> they
>>> would at time come in handy.
>>>
>>> On the subject of substitute and delayedAssign, I do have a follow-up
>>> question for the list. I'm trying to convert a named list of expression
>>> objects into an environment of promise objects. After conversion, each
>>> expression in the list will be automatically evaluated when the variable
>>> with the same name is accessed in the environment. Effectively, I'm
>>> trying
>>> to create a hash table of promise objects.
>>>
>>>
>> Populating a new environment with promises happens to be what "calling a
>> function" in R does anyway, so an elegant way to accomplish this goal is:
>>
>> makePromiseEnv <- function(expressions, parent=parent.frame()) {
>>      f <- function() environment()
>>      formals(f) <- as.pairlist(expressions)
>>      environment(f) <- parent
>>      f()
>> }
>>
>>  e <- makePromiseEnv(alist(a = {print("hello"); 4}, b = {print("again");
>>>
>> 6}))
>>
>>> e$a
>>>
>> [1] "hello"
>> [1] 4
>>
>>> e$a
>>>
>> [1] 4
>>
>>> e$b
>>>
>> [1] "again"
>> [1] 6
>>
>>> e$b
>>>
>> [1] 6
>>
>>
> I like that solution, except for one thing:  I don't see an easy way to
> control the environment where those expressions will be executed.  Since
> you've set them as defaults on the arguments, they will be evaluated in the
> evaluation frame of f(), and that might not be what we want. An obvious
> example of the problem would be
>
> e <- makePromiseEnv(alist(a = ls()))
>
> I don't know what Robert would want
>
> e$a
>
> to print, but one somewhat natural version would be to have it evaluate
> the ls() in the environment from which makePromiseEnv was called, i.e. the
> global environment in this case.  Neither your solution nor mine do this,
> but I can see how to modify mine, since it makes the evaluation environment
> of the expression explicit.  Can you see a modification that would do that
> with your approach?
>
> Duncan Murdoch
>

Sure, you could pass the expressions as arguments to f instead of as the
defaults. In this case do.call does the construction of promises.

makePromiseEnv2 <- function(expressions, envir=parent.frame()) {
  f <- function() environment()
  arglist <- expressions
  arglist[] <- list(quote(expr=))       #delete defaults, keep names
  formals(f) <- as.pairlist(arglist)
  do.call(f, expressions, envir=envir)
}

e <- makePromiseEnv2(alist(a=ls()))

	[[alternative HTML version deleted]]

