MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

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.)


  • Prev by Date: Re: Labeling points
  • Next by Date: Re: Problems with ListPlot
  • Previous by thread: Re: Implementing a array assignment for custom data structure
  • Next by thread: Problems with ListPlot