From Waclaw.Marcin.Kusnierczyk at idi.ntnu.no  Thu Feb  5 15:17:07 2009
From: Waclaw.Marcin.Kusnierczyk at idi.ntnu.no (Wacek Kusnierczyk)
Date: Thu, 05 Feb 2009 15:17:07 +0100
Subject: [Rd] Bug in the parser (?) (PR#13504)
In-Reply-To: <20090205131004.AE42C283415C@mail.pubhealth.ku.dk>
References: <20090205131004.AE42C283415C@mail.pubhealth.ku.dk>
Message-ID: <498AF4E3.1020902@idi.ntnu.no>

johnc.deva at yahoo.com wrote:
> Full_Name: John C. Deva
> Version: 2.8.1
> OS: Fedora Linux 8, 64 bit
> Submission from: (NULL) (193.200.150.189)
>
>
> I notice that it is possible to redefine 'if' as a function of an arbitrary
> number of arguments.  Such redefined 'if' can then be used as any other user
> function, except for that the parser still demands exactly three arguments to be
> given to if.  Furthermore, even if 'if' is defined with three arguments, its
> application must still be made with the original syntax, and not the usual
> syntax of function application:
>
>   
>> `if` <- function(a,b,c) 
>>     
> + {
> + assign(deparse(substitute(a)), b+c, envir=parent.frame()
> + }
>
>   
>> if (x) 1 else 2
>> x
>>     
> [1] 3
>
>   
>> if(x, 1, 2)
>>     
> Error: unexpected ',' in "if(x,"
>
> The later expression above should be the only valid when 'if' is redefined as
> above, but it is not the case.
>   

i've had a similar question discussed with peter dalgaard (i think)
offline (i think), with a close, though less tricky and exotic example. 
the issue is, when you redefine if, it does not propagate to the parser,
which still treats every occurrence of 'if' to be a keyword with the
usual syntactic constraints.  thus, the only way to apply such redefined
if is to use the original if syntax.

arguably, the parser could be parsing 'if' as a regular name in some
syntactic contexts, thus making you happily apply it as you want:

if(x) 1else 2 # parse as the conditional keyword 'if', since '1 else 2'
is present
if(x) 1 # likewise, since otherwise '1' after 'if(x)' would be
syntactically invalid
if() # parse as a function name, in a 0-argument call
if(x) # likewise, a 1-argument call
if(x, 1) # likewise, a 2-argument call
if(x, 1, 2) # likewise, ...
...

now you could redefine and use if as follows, for example (for whatever
reason might you wish to have if perform such weird actions):

if = function(...)
    assign(deparse(substitute(a)), sum(...), envir=parent.frame())
# note, no need to quote 'if' for the assignment
# if the parser would not force 'if' to be a keyword here

x = 0
if(x) 1 else 2
# 2
if(x) 1
# NULL, invisibly
if(x)
# x is sum()
if(x, 1)
# x is 1
if(x, 1, 2)
# x is 3

or maybe

if = function(if, x) if(if(x)) x else if
if(is.integer, 2)
# .Primitive("is.integer")
if(is.integer, 2L)
# 2

you probably don't really need to redefine if this way, or any other
way, but the point is valid, imho, and applicable to any other reserved
word.  it's rather weird that you *can* redefine if and use it as a
regular function but with the original syntax, as in your example.

you'll certainly get bashed for the bug report; it's not a bug, rather a
design issue, and not necessarily a problem.

vQ



[Rd] Bug in the parser (?) (PR#13504)
Wacek Kusnierczyk