with() and within() functions inside lapply() not seeing outside of its environment?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

with() and within() functions inside lapply() not seeing outside of its environment?

Pavel Krivitsky
Hi,

I have a list of sublists, and I want to add and/or remove elements in
each sublist in accordance with a code snippet. I had thought that an
elegant way to do that is using a combination of lapply() and within().
However, the code in the within() call doesn't seem to be able to see
objects outside of it. For (a simplified) example,

f <- function(x){
  y <- list(y1=list())
  y <- lapply(y, within, {z<-x})
  y
}
f(1)

My understanding is that what should happen is that lapply() would
execute

within(y[["y1"]], {z<-x}),

with 1 substituted for x, within() would notice that z has been assigned
1, returning list(z=1), which then gets put into a list as element named
"y1", so the function should ultimately return

list(y1=list(z=1))

What I get instead (on R 3.0.2 and current trunk, both on Linux) is

Error in eval(expr, envir, enclos) : object 'x' not found

Am I doing something wrong, or is this a bug?

                   Thanks in advance,
                   Pavel

P.S. If I "hard-code" the value for x, i.e.,

f <- function(){
  y <- list(y1=list())
  y <- lapply(y, within, {z<-1})
  y
}
f()

it returns list(y1=list(z=1)) as expected.

P.P.S. with() has the same problem:

f <- function(x){
  y <- list(y1=list())
  w <- lapply(y, with, x)
  w
}
f(1)

produces the exact same error as within().

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: with() and within() functions inside lapply() not seeing outside of its environment?

Duncan Murdoch-2
On 07/01/2014 10:35 AM, Pavel N. Krivitsky wrote:

> Hi,
>
> I have a list of sublists, and I want to add and/or remove elements in
> each sublist in accordance with a code snippet. I had thought that an
> elegant way to do that is using a combination of lapply() and within().
> However, the code in the within() call doesn't seem to be able to see
> objects outside of it. For (a simplified) example,
>
> f <- function(x){
>    y <- list(y1=list())
>    y <- lapply(y, within, {z<-x})
>    y
> }
> f(1)
>
> My understanding is that what should happen is that lapply() would
> execute
>
> within(y[["y1"]], {z<-x}),
>
> with 1 substituted for x, within() would notice that z has been assigned
> 1, returning list(z=1), which then gets put into a list as element named
> "y1", so the function should ultimately return
>
> list(y1=list(z=1))
>
> What I get instead (on R 3.0.2 and current trunk, both on Linux) is
>
> Error in eval(expr, envir, enclos) : object 'x' not found
>
> Am I doing something wrong, or is this a bug?
I wouldn't call it a bug, but it's a documented limitation, if you know
how to read it.  As documented, the expression is evaluated with the
caller's environment as the parent environment.  But here the caller is
some code in lapply, not your function f.  x is not found there.

I think this modification works, and is maybe the simplest way to get it
to work:

f <- function(x){
   y <- list(y1=list())
   mywithin <- function(...) within(...)
   y <- lapply(y, mywithin, {z<-x})
   y
}

The idea here is that the calling frame of f is the environment of
mywithin(), so x is found there.

Duncan Murdoch

>
>                     Thanks in advance,
>                     Pavel
>
> P.S. If I "hard-code" the value for x, i.e.,
>
> f <- function(){
>    y <- list(y1=list())
>    y <- lapply(y, within, {z<-1})
>    y
> }
> f()
>
> it returns list(y1=list(z=1)) as expected.
>
> P.P.S. with() has the same problem:
>
> f <- function(x){
>    y <- list(y1=list())
>    w <- lapply(y, with, x)
>    w
> }
> f(1)
>
> produces the exact same error as within().
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: with() and within() functions inside lapply() not seeing outside of its environment?

Peter Dalgaard-2

On 07 Jan 2014, at 19:19 , Duncan Murdoch <[hidden email]> wrote:

> I wouldn't call it a bug, but it's a documented limitation, if you know how to read it.  As documented, the expression is evaluated with the caller's environment as the parent environment.  But here the caller is some code in lapply, not your function f.  x is not found there.

I'd also consider it a bit brave to rely on ...-args to lapply being passed down unevaluated, but that does apparently work.

At any rate, you cannot both have x evaluated in the frame of f, and the assignment to z _not_ evaluated there.

>
> I think this modification works, and is maybe the simplest way to get it to work:
>
> f <- function(x){
>  y <- list(y1=list())
>  mywithin <- function(...) within(...)
>  y <- lapply(y, mywithin, {z<-x})
>  y
> }

There is also brute-force substitution:

> f <- function(x){
+  y <- list(y1=list())
+  y <- eval(bquote(lapply(y, within, {z<-.(x)})))
+  y
+ }
> f(1)
$y1
$y1$z
[1] 1



>
> The idea here is that the calling frame of f is the environment of mywithin(), so x is found there.
>
> Duncan Murdoch
>
>>
>>                    Thanks in advance,
>>                    Pavel
>>
>> P.S. If I "hard-code" the value for x, i.e.,
>>
>> f <- function(){
>>   y <- list(y1=list())
>>   y <- lapply(y, within, {z<-1})
>>   y
>> }
>> f()
>>
>> it returns list(y1=list(z=1)) as expected.
>>
>> P.P.S. with() has the same problem:
>>
>> f <- function(x){
>>   y <- list(y1=list())
>>   w <- lapply(y, with, x)
>>   w
>> }
>> f(1)
>>
>> produces the exact same error as within().
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

--
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Email: [hidden email]  Priv: [hidden email]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: with() and within() functions inside lapply() not seeing outside of its environment?

Pavel Krivitsky
In reply to this post by Duncan Murdoch-2
Hi,

> I wouldn't call it a bug, but it's a documented limitation, if you know
> how to read it.  As documented, the expression is evaluated with the
> caller's environment as the parent environment.  But here the caller is
> some code in lapply, not your function f.  x is not found there.

Thanks! That explains it.

> I think this modification works, and is maybe the simplest way to get it
> to work:
>
> f <- function(x){
>    y <- list(y1=list())
>    mywithin <- function(...) within(...)
>    y <- lapply(y, mywithin, {z<-x})
>    y
> }
>
> The idea here is that the calling frame of f is the environment of
> mywithin(), so x is found there.

It works.

                    Best regards,
                    Pavel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.