From Waclaw.Marcin.Kusnierczyk at idi.ntnu.no  Mon Mar 23 16:11:04 2009
From: Waclaw.Marcin.Kusnierczyk at idi.ntnu.no (Wacek Kusnierczyk)
Date: Mon, 23 Mar 2009 16:11:04 +0100
Subject: [Rd] incoherent treatment of NULL
In-Reply-To: <18887.41024.25380.419956@lynne.math.ethz.ch>
References: <49C74DC3.3090700@idi.ntnu.no>	<18887.22657.574884.473000@lynne.math.ethz.ch>	<49C75CD5.10903@idi.ntnu.no>
	<18887.41024.25380.419956@lynne.math.ethz.ch>
Message-ID: <49C7A688.7080501@idi.ntnu.no>

Martin Maechler wrote:
>
>  [...... omitted part no longer relevant ........]
>
>     WK> however, the following has a different pattern:
>     >> 
>     WK> x = NULL
>     WK> dput(x)
>     WK> # NULL
>     WK> names(x) = character(0)
>     WK> # error: attempt to set an attribute on NULL
>     >> 
>
>     WK> i get the error in devel.
>
> Yes,  NULL is NULL is NULL !   Do read  ?NULL !   [ ;-) ]
>
> more verbously,  all NULL objects in R are identical, or as the
> help page says, there's only ``*The* NULL Object'' in R,
> i.e., NULL cannot get any attributes.
>   

yes, but that's not the issue.  the issue is that names(x)<- seems to
try to attach an attribute to NULL, while it could, in principle, do the
same as class(x)<-, i.e., coerce x to some type (and hence attach the
name attribute not to NULL, but to the coerced-to object).

but, as someone else explained to me behind the scenes, the matters are
a little bit, so to speak, untidy:

    x = NULL
    class(x) = 'integer'
    # just fine

    x = NULL
    attr(x, 'class') = 'integer'
    # no go

where class()<-, but not attr(,'class')<-, will try to coerce x to an
object of the storage *mode* 'integer', hence the former succeeds
(because it sets, roughly, the 'integer' class on an empty integer
vector), while the latter fails (because it tries to set the 'integer'
class on NULL itself).

what was not clear to me is not why setting a class on NULL fails here,
but why it is setting on NULL in the first place.  after all,

    x = 1
    names(x) = 'foo'

is setting names on a *copy* of 1, not on *the* 1, so why could not
class()<- create a 'copy' of NULL, i.e., an empty vector of some type
(perhaps raw, as the lowest in the hierarchy).


>     WK> x = c()
>     WK> dput(x)
>     WK> # NULL
>     WK> names(x) = character(0)
>     WK> # error: attempt to set an attribute on NULL
>     >> 
>
>     WK> i get the error in devel.
>
> of course!  
>    [I think *you* should have noticed that  NULL and c()  *are* identical]
>
>     WK> and also:
>     >> 
>     WK> x = c()
>     WK> class(x) = 'integer'
>     WK> # fine
> "fine" yes; 
> here, the convention has been to change NULL into integer(0);
> and no, this won't change, if you find it inconsistent.
>   

that's ok, this is what i'd expect in the other cases, too (modulo the
actual storage mode).


>
>     WK> class(x) = 'foo'
>     WK> # error: attempt to set an attribute on NULL
>     >> 
>
>     WK> i get the error in devel.
>
> No, not if you evaluate the statements above (where 'x' has
> become  'integer(0)' in the mean time).
>
> But yes, you get in something like
>
>     x <- c();  class(x) <- "foo"
>   

that's what i meant, must have forgotten the x = c().

> and I do agree that there's a buglet : 
> The error message should be slightly more precise,
> --- improvement proposals are welcome ---
> but an error nontheless
>
>     WK> it doesn't seem coherent to me:  why can i set the class, 
>
> you cannot set it, you can *change* it.
>   

terminological wars? 

btw. the class of NULL is "NULL";  why can't nullify an object by
setting its class to 'NULL'?

    x = 1
    class(x) = 'NULL'
    x
    # *not* NULL

and one more interesting example:

    x = 1:2
    class(x) = 'NULL'
    x
    # [1] 1 2
    # attr(,"class") "NULL"
    x[1]
    # 1
    x[2]
    # 2
    is.vector(x)
    # FALSE

hurray!!! apparently, i've alchemized a non-vector vector...  (you can
do it in r-devel, for that matter).



>     WK> but not names
>     WK> attribute on both NULL and c()?  why can i set the class attribute to
>     WK> 'integer', but not to 'foo', as i could on a non-empty vector:
>
>     WK> x = 1
>     WK> class(x) = 'foo'
>     WK> # just fine
>
> mainly because 'NULL is NULL is NULL' 
> (NULL cannot have attributes)
>   

yes yes yes;  the question was, once again:  why is x still NULL?

>     WK> i'd naively expect to be able to create an empty vector classed 'foo',
>
> yes, but that expectation is wrong
>   

wrt. the actual state of matters, not necessarily wrt. the ideal state
of matters ;)  (i don't insist)

vQ



[Rd] incoherent treatment of NULL
Wacek Kusnierczyk