From wdunlap at tibco.com  Wed Mar 29 00:03:07 2017
From: wdunlap at tibco.com (William Dunlap)
Date: Tue, 28 Mar 2017 15:03:07 -0700
Subject: [Rd] A trap for young players with the lapply() function.
In-Reply-To: <0242d8a3-8d74-2036-e9a8-d1bfbd8aaef5@auckland.ac.nz>
References: <b2f95986-2a82-e9d7-d5a2-32ffac793461@auckland.ac.nz>
	<alpine.OSX.2.20.1703271912020.6811@charles-berrys-macbook.local>
	<0242d8a3-8d74-2036-e9a8-d1bfbd8aaef5@auckland.ac.nz>
Message-ID: <CAF8bMcYBhtpRVYo37ABjzko1sfbK0ck27c03xJ-kqpniykPjww@mail.gmail.com>

>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.

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 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
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] A trap for young players with the lapply() function.
William Dunlap