From luke-tierney at uiowa.edu  Mon Mar  2 00:07:23 2015
From: luke-tierney at uiowa.edu (luke-tierney at uiowa.edu)
Date: Sun, 1 Mar 2015 17:07:23 -0600
Subject: [Rd] iterated lapply
In-Reply-To: <20150301224345.GA2941@cs.toronto.edu>
References: <mailman.17.1425034805.31301.r-devel@r-project.org>
	<20150301171733.GA28691@cs.toronto.edu>
	<alpine.DEB.2.02.1503011329120.2327@luke-Latitude>
	<20150301224345.GA2941@cs.toronto.edu>
Message-ID: <alpine.DEB.2.02.1503011653250.2327@luke-Latitude>

On Sun, 1 Mar 2015, Radford Neal wrote:

>> There are other instances, such as Reduce where there is a bug
>> report pending that amounts to the same issue.  Performing surgery on
>> expressions and calling eval is not good practice at the R level and
>> probably not a good idea at the C level either.  It is worth thinking
>> this through carefully before a adopting a solution, which is what we
>> will be doing.
>
> Surgery on expressions is what lapply does at the moment.  My change
> makes it no longer do that.
>
> There is a general problem that lazy evaluation can have the effect
> of making the internal details of how an R function like "apply" is
> implemented leak into its semantics.  That's what's going on with
> the Reduce bug (16093) too.
>
> I think one can avoid this by defining the following function for
> calling a function with evaluation of arguments forced (ie, lazy
> evaluation disabled):
>
>  call_forced <- function (f, ...) { list (...); f (...) }
>
> (Of course, for speed one could make this a primitive function, which
> wouldn't actually build a list.)
>
> Then the critical code in Reduce could be changed from
>
>  for (i in rev(ind)) init <- f(x[[i]], init)
>
> to
>
>  for (i in rev(ind)) init <- call_forced (f, x[[i]], init)

This is the option I was suggesting as a possibility in my reply to
Bill Dunlap -- I called it funcall. This may be the right way to
go. There are some subtleties to sort out, such as how missing
arguments should be handled (allowed or error), and whether the force
should stop at ... arguments as in turning

     FUN(X[[i]], ...)

into

      funcall(FUN, X[[i]], ...)

There is also a change in when the evaluation of X[[i]] happens, which
may or may not matter.  Some testing against CRAN/BIOC packages should
reveal how much of an issue these are.

> If one had a primitive (ie, fast) call_forced, a similar technique
> might be better than the one I presented for fixing "apply" (cleaner,
> and perhaps slightly faster).  I don't see how it helps for functions
> like lapply that are written in C, however (where help isn't needed,
> since there's nothing wrong with the mod in my previous message).

If we adapt the funcall approach then it would be best if the C
implementation stayed as close as possible to an R reference
implementation. I do not think your proposed approach would do that.

mapply has its own issues with the MoreArgs argument that would be
nice to sort out at the same time if possible, as there are also a few
more instances of this in several places.

I will try to look into this more in the next week or so.

Best,

luke

>
>   Radford Neal
>

-- 
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   luke-tierney at uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu



[Rd] iterated lapply
luke-tierney at uiowa.edu