[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1

Rui Barradas ruipb@rr@d@@ @ending from @@po@pt
Thu Aug 30 18:16:00 CEST 2018


Hello,

Inline.

Às 16:44 de 30/08/2018, William Dunlap via R-devel escreveu:
> Should the following two functions should always give the same result,
> except for possible differences in the 'call' component of the warning
> or error message?:
> 
>    f0 <- function(x, y) x || y
>    f1 <- function(x, y) if (x) { TRUE } else { if (y) {TRUE } else { FALSE }
> }
> 
> And the same for the 'and' version?
> 
>    g0 <- function(x, y) x && y
>    g1 <- function(x, y) if (x) { if (y) { TRUE } else { FALSE } } else {
> FALSE }
> 
> The proposal is to make them act the same when length(x) or length(y) is
> not 1.
> Should they also act the same when x or y is NA?  'if (x)' currently stops
> if is.na(x)
> and 'x||y' does not.  Or should we continue with 'if' restricted to
> bi-valued
> logical and '||' and '&&' handling tri-valued logic?

I expect R to continue to do


f0(FALSE, NA)    # [1] NA
f0(NA, FALSE)    # [1] NA

g0(TRUE, NA)    # [1] NA
g0(NA, TRUE)    # [1] NA

f1(FALSE, NA)
#Error in if (y) { : missing value where TRUE/FALSE needed
f1(NA, FALSE)
#Error in if (x) { : missing value where TRUE/FALSE needed

g1(TRUE, NA)
#Error in if (x) { : missing value where TRUE/FALSE needed
g1(NA, TRUE)
#Error in if (x) { : missing value where TRUE/FALSE needed



Please don't change this.
There's more to the logical operators than the operands' lengths. That 
issue needs to be fixed but it doesn't mean a radical change should happen.
And the same goes for 'if'. Here the problem is completely different, 
there's more to 'if' than '||' and '&&'. Any change should be done with 
increased care. (Which I'm sure will, as always.)

Rui Barradas


> 
> 
> 
> Bill Dunlap
> TIBCO Software
> wdunlap tibco.com
> 
> On Thu, Aug 30, 2018 at 7:16 AM, Hadley Wickham <h.wickham using gmail.com> wrote:
> 
>> I think this is an excellent idea as it eliminates a situation which
>> is almost certainly user error. Making it an error would break a small
>> amount of existing code (even if for the better), so perhaps it should
>> start as a warning, but be optionally upgraded to an error. It would
>> be nice to have a fixed date (R version) in the future when the
>> default will change to error.
>>
>> In an ideal world, I think the following four cases should all return
>> the same error:
>>
>> if (logical()) 1
>> #> Error in if (logical()) 1: argument is of length zero
>> if (c(TRUE, TRUE)) 1
>> #> Warning in if (c(TRUE, TRUE)) 1: the condition has length > 1 and only
>> the
>> #> first element will be used
>> #> [1] 1
>>
>> logical() || TRUE
>> #> [1] TRUE
>> c(TRUE, TRUE) || TRUE
>> #> [1] TRUE
>>
>> i.e. I think that `if`, `&&`, and `||` should all check that their
>> input is a logical (or numeric) vector of length 1.
>>
>> Hadley
>>
>> On Tue, Aug 28, 2018 at 10:03 PM Henrik Bengtsson
>> <henrik.bengtsson using gmail.com> wrote:
>>>
>>> # Issue
>>>
>>> 'x || y' performs 'x[1] || y' for length(x) > 1.  For instance (here
>>> using R 3.5.1),
>>>
>>>> c(TRUE, TRUE) || FALSE
>>> [1] TRUE
>>>> c(TRUE, FALSE) || FALSE
>>> [1] TRUE
>>>> c(TRUE, NA) || FALSE
>>> [1] TRUE
>>>> c(FALSE, TRUE) || FALSE
>>> [1] FALSE
>>>
>>> This property is symmetric in LHS and RHS (i.e. 'y || x' behaves the
>>> same) and it also applies to 'x && y'.
>>>
>>> Note also how the above truncation of 'x' is completely silent -
>>> there's neither an error nor a warning being produced.
>>>
>>>
>>> # Discussion/Suggestion
>>>
>>> Using 'x || y' and 'x && y' with a non-scalar 'x' or 'y' is likely a
>>> mistake.  Either the code is written assuming 'x' and 'y' are scalars,
>>> or there is a coding error and vectorized versions 'x | y' and 'x & y'
>>> were intended.  Should 'x || y' always be considered an mistake if
>>> 'length(x) != 1' or 'length(y) != 1'?  If so, should it be a warning
>>> or an error?  For instance,
>>> '''r
>>>> x <- c(TRUE, TRUE)
>>>> y <- FALSE
>>>> x || y
>>>
>>> Error in x || y : applying scalar operator || to non-scalar elements
>>> Execution halted
>>>
>>> What about the case where 'length(x) == 0' or 'length(y) == 0'?  Today
>>> 'x || y' returns 'NA' in such cases, e.g.
>>>
>>>> logical(0) || c(FALSE, NA)
>>> [1] NA
>>>> logical(0) || logical(0)
>>> [1] NA
>>>> logical(0) && logical(0)
>>> [1] NA
>>>
>>> I don't know the background for this behavior, but I'm sure there is
>>> an argument behind that one.  Maybe it's simply that '||' and '&&'
>>> should always return a scalar logical and neither TRUE nor FALSE can
>>> be returned.
>>>
>>> /Henrik
>>>
>>> PS. This is in the same vein as
>>> https://mailman.stat.ethz.ch/pipermail/r-devel/2017-March/073817.html
>>> - in R (>=3.4.0) we now get that if (1:2 == 1) ... is an error if
>>> _R_CHECK_LENGTH_1_CONDITION_=true
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>>
>> --
>> http://hadley.nz
>>
>> ______________________________________________
>> R-devel using r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



More information about the R-devel mailing list