# Strange behaviour of UpSet [duplicate]

Can anyone explain what is going on here? I want to modify TensorRank for IdentityMatrix, but it fails on its first attempt:

Unprotect[IdentityMatrix];
Attributes[IdentityMatrix]

{}

TensorRank[IdentityMatrix[_]] ^= 2;


UpSet::write: Tag IdentityMatrix in TensorRank[IdentityMatrix[_]] is Protected. >>

Attributes[IdentityMatrix]

{Protected}


Huh?

Unprotecting it for the second time does work however:

Unprotect[IdentityMatrix];
TensorRank[IdentityMatrix[_]] ^= 2;
TensorRank[IdentityMatrix[n]]

2


This is on 9.0.1 for OS X, and I'm seeing the same behaviour on the cloud (version 10 for Linux).

-

## marked as duplicate by Mr.Wizard♦Oct 20 '14 at 16:36

It works fine for me in V10, Windows 8.1 –  RunnyKine Aug 8 '14 at 8:37
Indeed, I can reproduce this under V10 on Linux –  sebhofer Aug 8 '14 at 8:50
Confirmed in v9.0.1, Windows Vista 32bit. –  xzczd Aug 8 '14 at 8:53
This is starting to look like a bug. Can anyone else confirm that the first attempt forks for V10 on Windows? –  Teake Nutma Aug 8 '14 at 9:40
@sebhofer That makes sense, because TensorRank was introduced in V9. –  Teake Nutma Aug 8 '14 at 10:47

[Added: Virtually the same issue came up on StackOverflow a few years ago: Why do I have to evaluate this twice?]

I would not consider it a bug if the manipulation of System variables do no go the way you want. It turns out that the definition of TensorRank is not loaded until it is first evaluated. That initialization process resets the attributes of IdentityMatrix.

Quit[]

?? TensorRank


TensorRank[tensor] gives the rank of tensor. >>

(*
Attributes[TensorRank] = {Protected}

TensorRank := SystemDumpAutoLoad[Hold[TensorRank],
Hold[Grad,...,SymmetrizedArray],SymbolicTensorsSymbolicTensors] /; SystemDumpTestLoad
*)


The initial definition shows that the actual definition is auto-loaded when TensorRank is evaluated.

For what it's worth, you can UpSet the value of TensorRank[IdentityMatrix[_]] in one go by evaluating TensorRank first. In general, therefore, for similar sorts of redefinition of System symbols, the symbols should be evaluated first.

TensorRank;
IdentityMatrix; (* unnecessary, but following my own advice above *)
Unprotect[IdentityMatrix];
Attributes[IdentityMatrix]
(*
{}
*)

TensorRank[IdentityMatrix[_]] ^= 2;
(* no messages *)

TensorRank[IdentityMatrix["foo"]]
(* 2 *)

-
Thanks for the explanation. It still looks like a bug to me though: why would the autoloading of TensorRank reset properties of IdentityMatrix? –  Teake Nutma Aug 8 '14 at 11:08
@TeakeNutma Something like: Unprotect[IdentityMatrix]; (* make some new definitions *); Protect[IdentityMatrix]. The code seems to be in a .mx file, so I can't say specifically. I doubt the code would check the attributes and then reset them to what they were. Since IdentityMatrix is in fact a tensor, it is not surprising to me that the symbolic tensor code fiddles with it. (Evaluating TensorRank loads all the symbolic tensor code; the same thing happens if you evaluate TensorProduct or another such function.) –  Michael E2 Aug 8 '14 at 12:20
@MichaelE2 it looks like this is a bug. check the documentation example reference.wolfram.com/language/ref/ClearAttributes.html it is working fin from the first run before loading Log. I have faced same issue with Plus and Times. –  Algohi Aug 8 '14 at 16:02
@Algohi I think it is a conscious, intentional decision. But that is my personal opinion and we don't have to agree. The Log example is not strictly equivalent. TensorRank loaded a package that reset the attributes on IdentityMatrix; other functions may also reset attributes. The documentation does not guarantee that once an attribute is changed, it won't be changed again. BTW, another ref. is reference.wolfram.com/language/tutorial/…. –  Michael E2 Aug 8 '14 at 16:29