How do you check for a scalar in R?
I think is.atomic
suits your needs.
For why is.vector
is probably incompatible, see, e.g.:
is.atomic(list(1))
# [1] FALSE
is.vector(list(1))
# [1] TRUE
On your objects:
is.scalar <- function(x) is.atomic(x) && length(x) == 1L
is.scalar(doub)
# [1] TRUE
is.scalar(intg)
# [1] TRUE
is.scalar(c(doub, intg))
# [1] FALSE
Building on the answer by @MichaelChirico, there are a couple of other things that is.scalar()
should check for.
Firstly, complex numbers are not usually regarded as scalars (although I think this usage may vary between disciplines).
comp <- 2+3i
is.scalar <- function(x) is.atomic(x) && length(x) == 1L
is.scalar(comp)
# TRUE
so we should also check for complex numbers. The simple, but naive, way to do this is to use is.complex
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.complex(x)
is.scalar(comp)
# FALSE
Unfortunately, this is not quite right, because is.complex
just tests whether the class is "complex"
. But real numbers can have class=complex if their imaginary component is zero.
is.complex(2+0i)
# [1] TRUE
So to test for real numbers we are better off to check that the imaginary component is zero using Im(x)==0
. So, this leads us to a test for scalars that look like this
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && Im(x)==0
More trivially, characters ought also be eliminated
is.scalar("x")
# TRUE
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.character(x) && Im(x)==0
is.scalar("x")
# FALSE
Note that we test for is.character(x)
before Im(x)==0
so that lazy evaluation ensures that the function never tries to find the imaginary component of a character, which would throw an error.