Rolf Turner
2017-Mar-27 00:17 UTC
[Rd] A trap for young players with the lapply() function.
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> Error in get(as.character(FUN), mode = "function", envir = envir) : > object 'y' of mode 'function' was not foundThis 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 -- Technical Editor ANZJS Department of Statistics University of Auckland Phone: +64-9-373-7599 ext. 88276
Charles C. Berry
2017-Mar-28 02:26 UTC
[Rd] A trap for young players with the lapply() function.
On Mon, 27 Mar 2017, Rolf Turner wrote:> > 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 > >> Error in get(as.character(FUN), mode = "function", envir = envir) : >> object 'y' of mode 'function' was not found > > 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. >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
Rolf Turner
2017-Mar-28 21:30 UTC
[Rd] A trap for young players with the lapply() function.
On 28/03/17 15:26, Charles C. Berry wrote:> On Mon, 27 Mar 2017, Rolf Turner wrote: > >> >> 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 >> >>> Error in get(as.character(FUN), mode = "function", envir = envir) : >>> object 'y' of mode 'function' was not found >> >> 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. >> > > 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 )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 -- Technical Editor ANZJS Department of Statistics University of Auckland Phone: +64-9-373-7599 ext. 88276