[Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?

Michael Chirico m|ch@e|ch|r|co4 @end|ng |rom gm@||@com
Tue Nov 7 08:18:40 CET 2023


Thanks Martin. My hang-up was not on what the outcome of as.complex(NA)
should be, but rather, how I should read code like c(x, y) generally. Till
now, I have thought of it like 'c(x, y)' is c(as(x, typeof(y)), y)` when
"type(y) > type(x)". Basically in my mind, "coercion" in R <->
as.<newtype>(.) (or coerceVector() in C).

So I tracked down the source (which admittedly has been this way for much
longer than the present discussion) to see what exactly c() is doing in
this case:

https://github.com/r-devel/r-svn/blob/71e7480b07767f3b7d5c45a4247959aa4d83d910/src/main/bind.c#L418-L425

And indeed! It's not "coercion" in the sense I just described... there's a
branch for the 'x == NA_LOGICAL' case to _convert_ to NA_complex_.

On Mon, Nov 6, 2023 at 3:08 AM Martin Maechler <maechler using stat.math.ethz.ch>
wrote:

> >>>>> Michael Chirico
> >>>>>     on Sun, 5 Nov 2023 09:41:42 -0800 writes:
>
>     > This is another follow-up to the thread from September
>     > "Recent changes to as.complex(NA_real_)".
>
>     > A test in data.table was broken by the changes for NA
>     > coercion to complex; the breakage essentially comes from
>
>     > c(NA, 0+1i)
>     > # vs
>     > c(as.complex(NA), 0+1i)
>
>     > The former is the output we tested against; the latter is
> essentially (via
>     > coerceVector() in C) what's generated by our data.table::shift()
>
>     > However, these are now (r85472) different:
>
>     > Im(c(NA, 0+1i))
>     > # [1] NA  1
>     > Im(c(as.complex(NA), 0+1i))
>     > # [1] 0 1
>
>
>     > The former matches the behavior of directly using NA_complex_:
>
>     > Im(c(NA_complex_, 0+1i))
>     > # [1] NA  1
>
>     > On R4.3.2, they both match the NA_complex_ behavior:
>     > Im(c(NA, 0+1i))
>     > # [1] NA  1
>     > Im(c(as.complex(NA), 0+1i))
>     > # [1] NA 1
>
>     > Is this intended behavior, does something need to be updated for c()
> as
>     > well?
>
>     > Certainly it's messing with my understanding of how c() behaves,
> e.g. in ?c
>
>     >> All arguments are coerced to a common type which is the type of the
>     > returned value
>
> I think you have confused yourself, and everything behaves as expected:
>
> As we now have (in R-devel, since {r85233 | maechler | 2023-09-29 })
>
>   • ‘as.complex(x)’ now returns ‘complex(real=x, imaginary=0)’
>     for _all_ numerical and logical ‘x’, notably also for ‘NA’
>     or ‘NA_integer_’.
>
> ==> as.complex(NA) is indeed  complex(real = NA, imaginary = 0)
>
> And now, in your
>
>    c(as.complex(NA), 0+1i)
>
> you are calling c() on two complex numbers, i.e., there is *no* coercion
> (and c(.) is rather "trivial"),  and the same is true for
>
>    c(NA_complex_, 0+1i)
>
>
> However, in 85233, I had only modified & added examples to  ?as.complex,
> and now have added more (corresponding to the above NEWS entry);
> -> svn rev 85475
>
> .............
>
> The underlying "dilemma" that nobody can help us with is that
> "almost infinitely" many different complex numbers z fulfill
>  is.na(z) |--> TRUE
> and only one of them is  NA_complex_  and that may be unintuitive.
>
> OTOH, we already have for the doubles that there are at least two
> different x fulfulling is.na(x), namely  NaN and NA
> and from C's point of view there are even considerably more
> different NaN's .. but now I'm definitely digressing.
>
> Martin
>

	[[alternative HTML version deleted]]



More information about the R-devel mailing list