Henrik Bengtsson
2018-Aug-29 03:03 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
# 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 || yError 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
Emil Bode
2018-Aug-30 11:09 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
I have to disagree, I think one of the advantages of '||' (or &&) is the lazy evaluation, i.e. you can use the first condition to "not care" about the second (and stop errors from being thrown). So if I want to check if x is a length-one numeric with value a value between 0 and 1, I can do 'class(x)=='numeric' && length(x)==1 && x>0 && x<1'. In your proposal, having x=c(1,2) would throw an error or multiple warnings. Also code that relies on the second argument not being evaluated would break, as we need to evaluate y in order to know length(y) There may be some benefit in checking for length(x) only, though that could also cause some false positives (e.g. 'x==-1 || length(x)==0' would be a bit ugly, but not necessarily wrong, same for someone too lazy to write x[1] instead of x). And I don?t really see the advantage. The casting to length one is (I think), a feature, not a bug. If I have/need a length one x, and a length one y, why not use '|' and '&'? I have to admit I only use them in if-statements, and if I need an error to be thrown when x and y are not length one, I can use the shorter versions and then the if throws a warning (or an error for a length-0 or NA result). I get it that for someone just starting in R, the differences between | and || can be confusing, but I guess that's just the price to pay for having a vectorized language. Best regards, Emil Bode Data-analyst +31 6 43 83 89 33 emil.bode at dans.knaw.nl DANS: Netherlands Institute for Permanent Access to Digital Research Resources Anna van Saksenlaan 51 | 2593 HW Den Haag | +31 70 349 44 50 | info at dans.knaw.nl <mailto:info at dans.kn> | dans.knaw.nl <applewebdata://71F677F0-6872-45F3-A6C4-4972BF87185B/www.dans.knaw.nl> DANS is an institute of the Dutch Academy KNAW <http://knaw.nl/nl> and funding organisation NWO <http://www.nwo.nl/>. ?On 29/08/2018, 05:03, "R-devel on behalf of Henrik Bengtsson" <r-devel-bounces at r-project.org on behalf of henrik.bengtsson at 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 at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Joris Meys
2018-Aug-30 11:56 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
I have to agree with Emil here. && and || are short circuited like in C and C++. That means that TRUE || c(TRUE, FALSE) FALSE && c(TRUE, FALSE) cannot give an error because the second part is never evaluated. Throwing a warning or error for c(TRUE, FALSE) || TRUE would mean that the operator gives a different result depending on the order of the objects, breaking the symmetry. Also that would be undesirable. Regarding logical(0): per the documentation, it is indeed so that ||, && and isTRUE always return a length-one logical vector. Hence the NA. On a sidenote: there is no such thing as a scalar in R. What you call scalar, is really a length-one vector. That seems like a detail, but is important in understanding why this admittedly confusing behaviour actually makes sense within the framework of R imho. I do understand your objections and suggestions, but it would boil down to removing short circuited operators from R. My 2 cents. Cheers Joris On Wed, Aug 29, 2018 at 5:03 AM Henrik Bengtsson <henrik.bengtsson at 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 at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Joris Meys Statistical consultant Department of Data Analysis and Mathematical Modelling Ghent University Coupure Links 653, B-9000 Gent (Belgium) <https://maps.google.com/?q=Coupure+links+653,%C2%A0B-9000+Gent,%C2%A0Belgium&entry=gmail&source=g> ----------- Biowiskundedagen 2017-2018 http://www.biowiskundedagen.ugent.be/ ------------------------------- Disclaimer : http://helpdesk.ugent.be/e-maildisclaimer.php [[alternative HTML version deleted]]
Dénes Tóth
2018-Aug-30 12:03 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
Hi, I absolutely second Henrik's suggestion. On 08/30/2018 01:09 PM, Emil Bode wrote:> I have to disagree, I think one of the advantages of '||' (or &&) is the lazy evaluation, i.e. you can use the first condition to "not care" about the second (and stop errors from being thrown).I do not think Henrik's proposal implies that both arguments of `||` or `&&` should be evaluated before the evaluation of the condition. It implies that if an argument is evaluated, and its length does not equal one, it should return an error instead of the silent truncation of the argument. So your argument is orthogonal to the issue.> So if I want to check if x is a length-one numeric with value a value between 0 and 1, I can do 'class(x)=='numeric' && length(x)==1 && x>0 && x<1'. > In your proposal, having x=c(1,2) would throw an error or multiple warnings. > Also code that relies on the second argument not being evaluated would break, as we need to evaluate y in order to know length(y) > There may be some benefit in checking for length(x) only, though that could also cause some false positives (e.g. 'x==-1 || length(x)==0' would be a bit ugly, but not necessarily wrong, same for someone too lazy to write x[1] instead of x). > > And I don?t really see the advantage. The casting to length one is (I think), a feature, not a bug. If I have/need a length one x, and a length one y, why not use '|' and '&'? I have to admit I only use them in if-statements, and if I need an error to be thrown when x and y are not length one, I can use the shorter versions and then the if throws a warning (or an error for a length-0 or NA result). > > I get it that for someone just starting in R, the differences between | and || can be confusing, but I guess that's just the price to pay for having a vectorized language.I use R for about 10 years, and use regularly `||` and `&&` for the standard purpose (implemented in most programming languages for the same purpose, that is, no evaluation of all arguments if it is not required to decide whether the condition is TRUE). I can not recall any single case when I wanted to use them for the purpose to evaluate whether the *first* elements of vectors fulfill the given condition. However, I regularly write mistakenly `||` or `&&` when I actually want to write `|` or `&`, and have no chance to spot the error because of the silent truncation of the arguments. Regards, Denes> > Best regards, > Emil Bode > > Data-analyst > > +31 6 43 83 89 33 > emil.bode at dans.knaw.nl > > DANS: Netherlands Institute for Permanent Access to Digital Research Resources > Anna van Saksenlaan 51 | 2593 HW Den Haag | +31 70 349 44 50 | info at dans.knaw.nl <mailto:info at dans.kn> | dans.knaw.nl <applewebdata://71F677F0-6872-45F3-A6C4-4972BF87185B/www.dans.knaw.nl> > DANS is an institute of the Dutch Academy KNAW <http://knaw.nl/nl> and funding organisation NWO <http://www.nwo.nl/>. > > ?On 29/08/2018, 05:03, "R-devel on behalf of Henrik Bengtsson" <r-devel-bounces at r-project.org on behalf of henrik.bengtsson at 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 at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >
Dénes Tóth
2018-Aug-30 12:09 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
On 08/30/2018 01:56 PM, Joris Meys wrote:> I have to agree with Emil here. && and || are short circuited like in C and > C++. That means that > > TRUE || c(TRUE, FALSE) > FALSE && c(TRUE, FALSE) > > cannot give an error because the second part is never evaluated. Throwing a > warning or error for > > c(TRUE, FALSE) || TRUE > > would mean that the operator gives a different result depending on the > order of the objects, breaking the symmetry. Also that would be undesirable.Note that `||` and `&&` have never been symmetric: TRUE || stop() # returns TRUE stop() || TRUE # returns an error> > Regarding logical(0): per the documentation, it is indeed so that ||, && > and isTRUE always return a length-one logical vector. Hence the NA. > > On a sidenote: there is no such thing as a scalar in R. What you call > scalar, is really a length-one vector. That seems like a detail, but is > important in understanding why this admittedly confusing behaviour actually > makes sense within the framework of R imho. I do understand your objections > and suggestions, but it would boil down to removing short circuited > operators from R. > > My 2 cents. > Cheers > Joris > > On Wed, Aug 29, 2018 at 5:03 AM Henrik Bengtsson <henrik.bengtsson at 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 at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> > >
Hadley Wickham
2018-Aug-30 14:16 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
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 at 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 at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- http://hadley.nz
William Dunlap
2018-Aug-30 15:44 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
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? Bill Dunlap TIBCO Software wdunlap tibco.com On Thu, Aug 30, 2018 at 7:16 AM, Hadley Wickham <h.wickham at 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 at 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 at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > > -- > http://hadley.nz > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
Hugh Parsonage
2018-Sep-01 07:42 UTC
[Rd] ROBUSTNESS: x || y and x && y to give warning/error if length(x) != 1 or length(y) != 1
I would add my support for the change.>From a cursory survey of existing code, I'd say that usage like `class(x)== 'y'` -- rather than inherits(x, 'y') or is.y -- is probably going to be the major source of new warnings. So perhaps in the NEWS item it could be noted as a clue for developers encountering nascent warnings. Of course `if (class(x) == 'y')` already throws a warning, just not `if (class(x) == 'y' && TRUE)`. On Thu, 30 Aug 2018 at 21:09 Emil Bode <emil.bode at dans.knaw.nl> wrote:> I have to disagree, I think one of the advantages of '||' (or &&) is the > lazy evaluation, i.e. you can use the first condition to "not care" about > the second (and stop errors from being thrown). > So if I want to check if x is a length-one numeric with value a value > between 0 and 1, I can do 'class(x)=='numeric' && length(x)==1 && x>0 && > x<1'. > In your proposal, having x=c(1,2) would throw an error or multiple > warnings. > Also code that relies on the second argument not being evaluated would > break, as we need to evaluate y in order to know length(y) > There may be some benefit in checking for length(x) only, though that > could also cause some false positives (e.g. 'x==-1 || length(x)==0' would > be a bit ugly, but not necessarily wrong, same for someone too lazy to > write x[1] instead of x). > > And I don?t really see the advantage. The casting to length one is (I > think), a feature, not a bug. If I have/need a length one x, and a length > one y, why not use '|' and '&'? I have to admit I only use them in > if-statements, and if I need an error to be thrown when x and y are not > length one, I can use the shorter versions and then the if throws a warning > (or an error for a length-0 or NA result). > > I get it that for someone just starting in R, the differences between | > and || can be confusing, but I guess that's just the price to pay for > having a vectorized language. > > Best regards, > Emil Bode > > Data-analyst > > +31 6 43 83 89 33 > emil.bode at dans.knaw.nl > > DANS: Netherlands Institute for Permanent Access to Digital Research > Resources > Anna van Saksenlaan 51 | 2593 HW Den Haag > <https://maps.google.com/?q=Anna+van+Saksenlaan+51+%7C+2593+HW+Den+Haag&entry=gmail&source=g> > | +31 70 349 44 50 | info at dans.knaw.nl <mailto:info at dans.kn> | > dans.knaw.nl <applewebdata://71F677F0-6872-45F3-A6C4-4972BF87185B/ > www.dans.knaw.nl> > DANS is an institute of the Dutch Academy KNAW <http://knaw.nl/nl> and > funding organisation NWO <http://www.nwo.nl/>. > > ?On 29/08/2018, 05:03, "R-devel on behalf of Henrik Bengtsson" < > r-devel-bounces at r-project.org on behalf of henrik.bengtsson at 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 at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]