Skip to content

A trap for young players with the lapply() function.

5 messages · Charles C. Berry, Rolf Turner, William Dunlap

#
From time to time I get myself into a state of bewilderment when using
apply() by calling it with FUN equal to a function which has an 
"optional" argument named "X".

E.g.

     xxx <- lapply(y,function(x,X){cos(x*X)},X=2*pi)

which produces the error message
This of course happens because the name of the first argument of 
lapply() is "X" and so it takes the value of this first argument to be 
the supplied X (2*pi in the foregoing example) and then expects what the 
user has denoted by "y" to be the value of FUN, and (obviously!) it isn't.

Once one realises what is going on, it's all quite obvious, and usually
pretty easy to fix.  OTOH there are lots of functions around with second
or third arguments whose formal name is "X", and these can trip one up
until the penny drops.

This keeps happening to me, over and over again (with sufficiently long
intervals between occurrences so that my ageing memory forgets the 
previous occurrence).

Is there any way to trap/detect the use of an optional argument called 
"X" and thereby issue a more perspicuous error message?

This would be helpful to those users who, like myself, are bears of very 
little brain.

Failing that (it does look impossible) might it not be a good idea to 
add a warning to the help for lapply(), to the effect that if FUN has an 
optional argument named "X" then passing this argument via "..." will 
cause this argument to be taken as the first argument to lapply() and 
thereby induce an error?

cheers,

Rolf Turner
1 day later
#
On Mon, 27 Mar 2017, Rolf Turner wrote:

            
The lapply help page addresses this issue in `Details' :

"it is good practice to name the first two arguments X and FUN if ... is 
passed through: this both avoids partial matching to FUN and ensures that 
a sensible error message is given if arguments named X or FUN are passed 
through ..."

So that advice suggests something like:

xxx <- lapply( X=y, FUN=function(X,x){cos(X*x)}, x=2*pi )

Best,

Chuck
#
On 28/03/17 15:26, Charles C. Berry wrote:
That is of course very sound advice, but it pre-supposes that the user 
is *aware* that there is a pitfall to be avoided.  I was hoping for 
something that would protect dweebs like myself from the pitfall given 
that we are too obtuse to be cognizant of its existence.

I think that the suggestion I made, in response to a posting by Barry 
Rowlingson, that the first argument of lapply() be given the name of 
".X" rather than just-plain-X, would be (a) effective, and (b) harmless.

cheers,

Rolf
#
It would break any call to *apply() that used X= to name the first
argument.  There are currently 3020 such calls in the R code in CRAN.

One can avoid the problem by creating the function given as the FUN
argument when one calls lapply() and the like.  Don't give that
function arguments named "X", "FUN", "USE.NAMES", etc. and perhaps
make use of R's lexical scoping to avoid having to use many arguments
to the function.  E.g., instead of
    sapply(1:5, sin)
use
    sapply(1:5, function(theta) sin(theta))
or instead of
    myY <- 3
    sapply(1:5, atan2, y=myY)
use
    myY <- 3
    sapply(1:5, function(x) atan2(myY, x))

Bill Dunlap
TIBCO Software
wdunlap tibco.com
On Tue, Mar 28, 2017 at 2:30 PM, Rolf Turner <r.turner at auckland.ac.nz> wrote:
#
On 29/03/17 11:03, William Dunlap wrote:

            
Okay.  Scratch that idea.
Again, all very sound advice but it does not address the problem of 
there being a trap for young players.  The advice can only be applied by 
a user only if the user is *aware* of the trap.

At this point it would appear that the problem is fundamentally 
unsolvable. :-(

cheers,

Rolf