Skip to main content
added 340 characters in body
Source Link
Kuba
  • 138.9k
  • 13
  • 297
  • 803

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.

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} 

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.

Source Link
Kuba
  • 138.9k
  • 13
  • 297
  • 803

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}