7
$\begingroup$

The Attributes function itself has the attributes:

Attributes[Attributes]
{HoldAll,Listable,Protected}

In particular, it is Protected which prevents me from redefining it:

Attributes = Foo
During evaluation of In[2]:= Set::wrsym: Symbol Attributes is Protected. >>

Foo

however, I am able to modify Attributes if I associate to a symbol:

Attributes[Foo] = {Protected}
{Protected}

which seems strange to me, because other functions which are Protected can't do this. For example, with this newly protected Foo function, the following fails:

Foo[a] = 5
During evaluation of In[5]:= Set::write: Tag Foo in Foo(a) is Protected. >>

 5

So how does the Protected attribute really work, and what makes the situation with the Attributes function different from my simple Foo function? Is it possible to have Foo work in the same way as Attributes?

$\endgroup$
5
$\begingroup$

It is because Attributes have UpValues(*) associated with them so at the end you are not trying to Set to Attributes[Foo] but it will be translated.

You can mimic that with e.g. UpSetDelayed (^:=):

ClearAll[f]

Set[f[x_], attr_] ^:= SetAttributes[x, attr];

SetAttributes[f, {Protected, HoldFirst}]

f = 2
Set::wrsym: Symbol f is Protected. >>
f[x] = HoldFirst (*no error*)

Attributes[x]
{HoldFirst}

(*) Though I'm not sure if that is indeed the functionality used since <<GeneralUtilities` and PrintDefinitions @ Attributes shows something like _[___, Attributes, ___] := <<kernel function>>;. It's probably done in a slightly different way, not accesible to user(?), but I believe my point is valid.

$\endgroup$
  • $\begingroup$ Thanks for that! I originally figured it could be to do with Set, but I had no idea that it could be used in this way. $\endgroup$ – JP-Ellis Apr 27 '16 at 6:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.