From r.turner at auckland.ac.nz  Thu Mar 30 04:53:39 2017
From: r.turner at auckland.ac.nz (Rolf Turner)
Date: Thu, 30 Mar 2017 15:53:39 +1300
Subject: [Rd] A trap for young players with the lapply() function.
In-Reply-To: <87d1d0a66x.fsf@enricoschumann.net>
References: <4e15ccb966c041f68ea042459324d02c@EX-0-HT0.lancs.local>
	<CANVKczOEg6e3b7U1rYd1nQzJQOtxXGc+e=6cvHJJVFSsxcovAQ@mail.gmail.com>
	<5c05350f-ea20-b8c2-5f97-2af3a05f9052@auckland.ac.nz>
	<87d1d0a66x.fsf@enricoschumann.net>
Message-ID: <ee0da8f1-ae28-9bf7-0c8d-d4609adde5ac@auckland.ac.nz>

On 29/03/17 20:32, Enrico Schumann wrote:
> (inline)
>
> On Tue, 28 Mar 2017, Rolf Turner writes:
>
>> On 28/03/17 04:21, Barry Rowlingson wrote:
>>> On Mon, Mar 27, 2017 at 1:17 AM, Rolf Turner <r.turner at auckland.ac.nz> wrote:
>>>>
>>>> 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)
>>>
>>> You can get the names of named arguments:
>>>
>>>  > z = function(x,X){cos(x*X)}
>>>  > names(formals(z))
>>>  [1] "x" "X"
>>
>> That doesn't seem to help.  I tried putting a browser inside lapply()
>> and looked at formals(FUN).  This gave NULL, because FUN has already
>> been taken to be the list argument "x" to which lapply() is being
>> applied.
>
> You can get the call, without the arguments being
> matched, with `sys.call`. In your call of lapply,
> saying `sys.call()` before anything else would give
> you
>
>
>     lapply(y, function(x, X) {
>         cos(x * X)
>     }, X = 2 * pi)
>
> which would allow you to get at the argument names of
> your function.
>
>     if ("X" %in% names(sys.call()[[3L]][[2L]]))
>        warnings("found 'X'")
>
> But more would be needed: you need to figure out which
> argument you actually meant to be FUN. (In the above,
> I simply assumed it was the second passed argument.)
> That is, you would need to figure out which passed
> argument is a function, which is not safe either,
> since ... may also contain functions.


This idea appears to work for the particular example that I used, but it 
is not clear to me how to make it work in general.  E.g. if we define

   foo <- function(x,X){X*x}

and then do

   lapply(xxx,foo,X=2*pI)

we find that sys.call[[3]] is of length 1 and consists only of the 
*name* "foo".  One can then inspect

    formals(get(as.character(sys.call[[3]])))

and find "X" therein, on the basis of which to trigger a warning.

However I don't know how to approach distinguish the two cases, or how 
to discern if there may be other cases lurking in the bushes.

So the problem still looks insoluble to me.

cheers,

Rolf

-- 
Technical Editor ANZJS
Department of Statistics
University of Auckland
Phone: +64-9-373-7599 ext. 88276



[Rd] A trap for young players with the lapply() function.
Rolf Turner