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

2022-10-24 Thread Bert Gunter
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  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
>  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"); 

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

2022-10-24 Thread Bert Gunter
"...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
 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@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.

__
R-help@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.


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

2022-10-24 Thread Jorgen Harmse via R-help
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@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.