On Fri, 18 Feb 2005, Peter Dalgaard wrote:
Luke Tierney <[EMAIL PROTECTED]> writes:
looks like eapply has an extra eval in the code. It does because the
code creates a call of the form
FUN(<value>)
with the literal value in place and then calls eval on this, which
results in calling eval on value. The internal lapply in contrast
creates a call of the form
FUN(<list>[[<index>]])
and evals that. This causes the literal <list> and <index> values to
be evaluated, which is OK since they are guaranteed to be a list
(generic vector) and integer vector and so evaluate to themselves, and
the call to [ is then evaluated, returning what is in the list at the
appropriate index and passing that, without further evluation, to FUN.
The semantics we want in eapply is I think equivalent to creating
FUN(get(<name>, <envir>))
Or, as I was suggesting,
eval(substitute(F(x), list(F=FUN,x=as.name(e)), envir)
Well, you know my view of adding more nonstandard evaluation. Any
explicit use of eval is almost always a Really Bad Idea, and in most
of the remaining cases it is a bad idea. In any cases that still
remain it should be avoinded if at all possible. And if it seems not
possible then it is best to put the problem down for a while and think
a bit more....
and evaluating that, but we are not getting this. Direct use of this
would be less efficient that the current approach, but using
FUN(quote(<value>))
as the constructed call should do the trick.
You have to be careful only to do this if the value is of mode "call",
I think. Or is quote always a no-op in the other cases?
quote is fine--it always returns the object that appears as the
argument in the call. For quote expressions created as the result of
parsing that will be a somewhat limited set of things, but for quote
calls created programmatically it can be anything.
I'm getting a bit fond of the the solution that I had because it will
also work if the FUN uses deparse(substitute(....)) constructions, and
once you're at the level of constructing calls via LCONS() it isn't
really inefficient either. Extra arguments could be a bit of a bother
though. (What happens to those currently?? The function doesn't seem to
pass them to .Internal.)
I believe none of our apply family of functions can be expected to do
anything very useful in situations that require nonstandard evaluation
based on the call context. I don't beieve we explicitly document what
is supposed to happen here (and I'm not sure we want to at least at
this point: this is the sort of thing where leaving it undefined gives
alternate implementations, such as one based on compilation, some room
to work with). But it might be worth thinking about narrowing
variability a little. A somewhat related issue is that we don't have
a completely standard mechanism of calling an function from within C
code--we do it by creating and eval'ing (in C) a call expression, but
there may be some slight variations in the way it is done in different
places that we might want to think about at some point.
For this specific case though, I _think_ the semantics we want is this:
eapply1 <- function(env, FUN, ..., all.names = FALSE) {
FUN <- match.fun(FUN)
lapply(.Internal(env2list(env, all.names)), FUN, ...)
}
Not passing the ... in the current implementation is, I think, an
oversight, as is the extra evaluation that occurs. Given that lapply
is already internal I'm not sure there really is very much benefit in
having the internal eapply. If not I'd prefer to replace it by
something like this; if there are reasons for keeping the .Internal we
can work on replicating these semantics as closely as possible. I
think Robert is the one who would know the issues.
luke
--
Luke Tierney
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: [EMAIL PROTECTED]
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel