Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Part

▪ You can make an assignment like t[[spec]]=value to modify any part or sequence of parts in an expression.

▪ If expr is a SparseArray object, expr[[...]] gives the parts in the corresponding ordinary array.

SparseArray

▪ List and matrix operations are typically set up to work as they do on Normal[SparseArray[...]].

Part extracts specified parts of the array represented by a SparseArray object, rather than parts of the SparseArray expression itself.

array = Range[10]
(* {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} *)

array[[2]] = Sequence[0, 0, 0];

array
(* {1, 0, 0, 0, 3, 4, 5, 6, 7, 8, 9, 10} *)

sparse = SparseArray[Range[10]];

sparse[[2]] = Sequence[0, 0, 0];

sparse[[2]]
(* {10} *)

ArrayRules[sparse]
(* ArrayRules::rect: Nonrectangular array encountered. >> *)
(* ArrayRules[SparseArray[Automatic, {10}, 0,
     {1, {{0, 10}, {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}}}, 
     {1, 0, 0, 0, 3, 4, 5, 6, 7, 8, 9, 10}}]] *)

Is it a bug?

share|improve this question
    
After reading this answer I think that maybe the former case with Lists works only by a happy accident. –  Vladimir Reshetnikov Jun 25 '13 at 3:46
    
You might find this discussion interesting, as well as the other one linked to there in my post there. –  Leonid Shifrin Jun 25 '13 at 8:41

1 Answer 1

Analysis

It indeed looks like a borderline bug to me. Let us see what is happening. The first observation here is that part assignment does its job all right:

sparse = SparseArray[Range[10]];
sparse[[2]] = Sequence[0, 0, 0];

so that

?sparse
Global`sparse
sparse=SparseArray[Automatic,
   {10},0,{1,{{0,10},{{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}}},
   {1,Sequence[0,0,0],3,4,5,6,7,8,9,10}}
]

you can see that the actual rule for sparse was updated correctly.

The next observation is that the main culprit is the SparseArray object, which evaluates, and in particular the Sequence inside the list of elements gets spliced, as it should according to the main evaluation procedure:

sparse

(* 
     SparseArray[
        Automatic,{10},0,{1,{{0,10},{{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}}},
       {1,0,0,0,3,4,5,6,7,8,9,10}}
     ]
*)

while this is consistent with the evaluation sequence, this is where it goes wrong. To avoid this, either SparseArray should be HoldAll:

SetAttributes[SparseArray, HoldAll]

and then it works:

ArrayRules[sparse]

(* 
  {{1}->1,{2}->Sequence[0,0,0],{3}->3,{4}->4,{5}->5,{6}->6,
    {7}->7,{8}->8,{9}->9,{10}->10,{_}->0}
*)

or, the elements inside of SparseArray should be held in some holding wrapper (Hold etc), rather than List.

ClearAttributes[SparseArray, HoldAll]

The second option would require significant changes in the SparseArray representation, so it is unlikely that such a change can be considered. I can't tell off hand whether making SparseArray HoldAll can break anything.

Workarounds

You can create a dynamic environment to do that locally:

ClearAll[withHoldingSparseArray];
SetAttributes[withHoldingSparseArray,HoldAll];
withHoldingSparseArray[code_]:=
    Internal`InheritedBlock[{SparseArray},
       SetAttributes[SparseArray,HoldAll];
       code
    ];

so that

withHoldingSparseArray[ArrayRules[sparse]]

(* 
  {{1}->1,{2}->Sequence[0,0,0],{3}->3,{4}->4,{5}->5,{6}->6,
    {7}->7,{8}->8,{9}->9,{10}->10,{_}->0}
*)

As another alternative, you can create a dynamic environment where you make Sequence inert:

ClearAll[withInertSequence];
SetAttributes[withInertSequence,HoldAll];
withInertSequence[code_]:=
    Module[{result,sequence},                        
        Block[{Sequence=sequence},
            result=code
        ];
        sequence=Sequence;
        result
    ]

and this will also give the right result for your example:

withInertSequence[ArrayRules[sparse]]

(* 
  {{1}->1,{2}->Sequence[0,0,0],{3}->3,{4}->4,{5}->5,{6}->6,
    {7}->7,{8}->8,{9}->9,{10}->10,{_}->0}
*)

This method can however be more dangerous / prone to errors than the first one.

Conclusions

So, on one hand, SparseArray object evaluates precisely according to the standard evaluation semantics. On the other hand, this leads to behavior which one can probably classify as a bug. I'll file a report on this.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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