Thanks for spotting this issue. The short answer is yes, adding
attributes to a symbol is a bad idea and will be turned into a runtime
error soon. Maintainers of packages that add attributes to symbols have
been notified and some have already fixed their code.
At least in one case the package is not working properly, even in
isolation, because of the global effect of adding an attribute to a
symbol. Think about an expression "x - x", adding sign 1 to the
"first
x" and then sign -1 to the "second x" ends up with (both)
"x" having
sign "-1", because it is the same "x". The package would
need something
like a symbol, but passed by value (suggestions below).
By design in R symbols are represented by singleton objects registered
in a global symbol table. Symbols are passed by reference and are fully
represented by their name or pointer, so they can be quickly compared by
pointer comparison and they can be used for bindings (naming variables,
functions). Symbols thus cannot have attributes attached and must be
treated as immutable. For this reason also attributes on symbols are not
preserved on serialization (as Radford pointed out).
In some cases one needs to add an attribute to something similar to a
symbol, but something passed by value. There are multiple ways to do it
(credits for suggestions to Peter, Michael and others):
- wrap a symbol into an object passed by value, add an attribute to that
object; such an object can be a list, an S3 or S4 object, an expression,
etc; in "x - x", there will be two different wrappers of "x"
- encapsulate a symbol and needed meta-data (what would be in the
attribute) together into an object passed by value, e.g. into S3/S4
object or a list; in "x - x", there will again be two different
objects
encapsulating "x"
- store the meta-data (what would be in the attribute) in a user
environment created by new.env(); the meta-data could be conveniently
looked up by the symbol and the environment can be hashed for fast
lookup; from Peter:> attrib <- new.env()
> attributes(sym) ----> attrib$sym
> attr(sym, "foo") ----> attrib$sym[["foo"]]
(the last suggestion will not work for the example "x-x", but may work
for other where referential semantics is needed, but now in a well
defined scope)
Best,
Tomas
On 07/07/2017 03:06 PM, Torsten Hothorn wrote:>
> Here is a simpler example:
>
>> ex <- as.name("a")
>> attr(ex, "test") <- 1
>> quote(a)
> a
> attr(,"test")
> [1] 1
>
> Torsten
>
> On Thu, 6 Jul 2017, William Dunlap wrote:
>
>> The multcomp package has code in multcomp:::expression2coef that
>> attaches the 'coef' attribute to
>> symbols. Since there is only one symbol object in a session with a
>> given name, this means that
>> this attaching has a global effect. Should this be quietly allowed
>> or should there be a warning or
>> an error?
>> E.g.,
>>
>> str(quote(Education))
>> # symbol Education
>> lmod <- stats::lm(Fertility ~ ., data = datasets::swiss)
>> glmod <- multcomp::glht(lmod, c("Agriculture=0",
"Education=0"))
>> str(quote(Education))
>> # symbol Education
>> # - attr(*, "coef")= num 1
>>
>> Bill Dunlap
>> TIBCO Software
>> wdunlap tibco.com
>>
>>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel