Re: Implementing a array assignment for custom data structure

*To*: mathgroup at smc.vnet.net*Subject*: [mg88915] Re: Implementing a array assignment for custom data structure*From*: Szabolcs Horvát <szhorvat at gmail.com>*Date*: Wed, 21 May 2008 14:50:02 -0400 (EDT)*Organization*: University of Bergen*References*: <g0tqub$mj9$1@smc.vnet.net>

Salvatore Mangano wrote: > Lists support a convenient syntax for element assignment: > > a[[i]]=v > > Of course this syntax is syntactic sugar for: > > Set[Part[a, i], v] > > > SparseArray's have a different structure than lists but still support the same syntax. > > This leads me to believe that I should be able to implement a custom type (akin to SparseArray) that also allows this syntax (possibly using UpValues) but for the life of me I can't see how to accomplish this. > > Any ideas? One is always reluctant to say that something is impossible because of the possibility of being proven wrong ... but I believe that this cannot be done. Here are a few examples to demonstrate why. I shall use the symbol part instead of Part (because I do not want to assign rules to Part). Let the custom data structure be myList, whose argument is a normal List. SetAttributes[myList, HoldAll] l = {1, 2, 3} x = myList[l] We shall consider the nth element of x to be equivalent to the nth element of l. We want to allow setting e.g. the 2nd element of x to 5 with the following command: part[x, 2] = 5 The implementation that might spring to mind first is myList /: Set[part[myList[a_], n_], val_] := (a[[n]] = val) But this does not work. The reason is that myList is 2 levels deep inside the pattern, so an UpValue cannot be assigned to it. We need to assign the UpValue to part. Unfortunately this is already a problem, because one does not feel safe modifying Part ... The next try could look like this part /: Set[part[myList[a_], n_], val_] := (a[[n]] = val) But this still does not work ... It turns out that the reason is that Set is HoldFirst, so Set[part[x,2], 5] keeps x unevaluated (and it cannot match myList). Here's a fairly complicated version that does work: part /: Set[part[ml_ /; Head[ml] === myList, n_], val_] := Extract[ml, 1, Function[{lst}, lst[[n]] = val, {HoldAll}]] (The complicated RHS is for extracting the argument of the myList object without actually evaluating it. It is not really relevant for the example.) So it seems that what you are asking for can only be accomplished by modifying Part or Set. I strongly recommend against attempting anything like this. Also note that sparse arrays are treated specially by Mathematica. They are considered atoms (AtomQ returns True), and many structure manipulation functions beside Part work on them (e.g. Map, etc.)