[R] unexpected 'else' in " else" (Ebert,Timothy Aaron)

Bert Gunter bgunter@4567 @end|ng |rom gm@||@com
Mon Oct 24 19:07:35 CEST 2022


I wanted to follow up.
A more careful reading of the following:
"A vector of the same length and attributes (including dimensions and
"class") as test..."

So the above **refers only to a "class" attribute that appears among
the attributes of test and result**. Using my previous example, note
that:

 z <- c(TRUE,TRUE,FALSE)
> attributes(z)
NULL ## so no 'class' among attributes(z)
## However
> class(z)  ## S3 class
[1] "logical"
## Similarly
> w <- ifelse(z,5,'a')
> attributes(w)
NULL ## so no 'class' among attributes(w)
> class(w)   ##S3 class
[1] "character"

So my (anyway) confusion stems from conflating the S3 'class' of the
object with a "class" attribute, of which there is none.

Nevertheless, I believe that the phrase I suggested (or something
along those lines) might clarify how the S3 class is determined and
perhaps better distinguish it from a "class" attribute among the
attributes, if there there is such. Or maybe that part of the doc
should just be removed.

My guess is that this documentation has been around for a long time
and no one has gotten around to revising it once S3 classes came into
wider use. ... or saw the need to revise it, anyway.

-- Bert





"

On Mon, Oct 24, 2022 at 9:30 AM Bert Gunter <bgunter.4567 using gmail.com> wrote:
>
> "...but 'same length and attributes (including dimensions and
> ‘"class"’) as ‘test’' looks wrong. The output seems to be `logical` or
> something related to the classes of `yes` & `no`."
>
> The documentation in fact says:
> "A vector of the same length and attributes (including dimensions and
> "class") as test and data values from the values of yes or no. **The
> mode of the answer will be coerced from logical to accommodate first
> any values taken from yes and then any values taken from no.**
>
> So the values are taken from 'yes' and 'no' (with coercion if they are
> of different classes), and the class of the result will presumably be
> inferred from the mode of those values. e.g.
>
> > z <- c(TRUE,TRUE,FALSE)
> > class(z)
> [1] "logical"
> > w <- ifelse(z,5,'a')
> > class(w)
> [1] "character"  ## note coercion
>
> So it would appear that the ifelse() documentation needs to be
> clarified. For example, if the above asterisked phrase were "The S3
> *class* of the answer will be inferred from the mode, where the mode
> of the answer will be coerced ..." that might resolve at least that
> bit of confusion However, that might also be incorrect -- what about
> S4 vs S3 vs Reference classes, for example (are such cases even
> possible?)? I leave resolution of these matters -- or at least their
> accurate and complete documentation -- to wiser heads.
>
> Cheers,
> Bert
>
>
>
>
> On Mon, Oct 24, 2022 at 8:45 AM Jorgen Harmse via R-help
> <r-help using r-project.org> wrote:
> >
> > There were several interesting points about `ifelse`. The usual behaviour seems to be that all three inputs are evaluated, and the entries of `yes` corresponding to `TRUE` in `test` are combined with the entries of `no` corresponding to `FALSE` in `test`. Moreover, `yes` & `no` seem to be recycled as necessary in case `test` is longer. On top of that, there seems to be some sugar that suppresses evaluations in case `all(test)` and/or `all(!test)`, and the return type can be `logical` even if `yes` & `no` are not. I agreed with the other responses already, but my experiments further confirmed that `ifelse` is not interchangeable with `if(....) .... else ....`.
> >
> >
> >
> > The documentation confirms most of this, but 'same length and attributes (including dimensions and ‘"class"’) as ‘test’' looks wrong. The output seems to be `logical` or something related to the classes of `yes` & `no`.
> >
> >
> >
> > Regards,
> >
> > Jorgen Harmse.
> >
> >
> >
> > > ifelse(FALSE, {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'else'.
> >
> > [1] 0
> >
> > > ifelse(rep(FALSE,5L), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'else'.
> >
> > [1] 0 1 2 3 4
> >
> > > ifelse(rep(TRUE,3L), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'if'.
> >
> > [1] 1 2 3
> >
> > > ifelse(c(TRUE,TRUE,FALSE), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'if'.
> >
> > Evaluating the vector for 'else'.
> >
> > [1] 1 2 2
> >
> > > ifelse(c(TRUE,TRUE,FALSE,TRUE), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'if'.
> >
> > Evaluating the vector for 'else'.
> >
> > [1] 1 2 2 1
> >
> > > args(ifelse)
> >
> > function (test, yes, no)
> >
> > NULL
> >
> > > ifelse(c(TRUE,TRUE,FALSE,TRUE,TRUE,FALSE,TRUE), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > Evaluating the vector for 'if'.
> >
> > Evaluating the vector for 'else'.
> >
> > [1] 1 2 2 1 2 0 1
> >
> > > ifelse(logical(0L), {cat("Evaluating the vector for 'if'.\n"); 1:3}, {cat("Evaluating the vector for 'else'.\n"); 0:4})
> >
> > logical(0)
> >
> > > ifelse(TRUE, integer(0L), numeric(0L))
> >
> > [1] NA
> >
> > > class(ifelse(TRUE, integer(0L), numeric(0L)))
> >
> > [1] "integer"
> >
> > > ifelse(integer(0L)) # test is an empty vector of integers and yes & no are missing.
> >
> > logical(0)
> >
> >
> >
> >
> >
> >
> >
> >
> >         [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> > and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list