Skip to main content
added 1399 characters in body
Source Link
shopper
  • 319
  • 1
  • 7

Edit:


I think in my original post, I missed emphasizing the main point. This is mainly a pattern matching question. If you're interested in the 'why' of this question, please read the original post below. The short question:

Suppose I have a newly defined, unevaluated Head, called NewHead. I define a function associated with NewHead as (I add in the x & y to emphasize that the argument list can be arbitrary so long as it contains n_NewHead)

In[1]= NewHead /: func[x_, n_NewHead, y_] := n 

This has

In[2]= UpValues[NewHead] Out[2]= {HoldPattern[func[x_, n_NewHead, y_]] :> n} 

I would like to use pattern matching so I can transform this UpValue list like

In[3]= UpValues[NewHead] /. (* Some pattern matching here resulting in: *) Out[3]= {HoldPattern[func[x_, d_DerivedHead, y_]] :> func[x, d[[1]], y]} 

The point is to make a 'class' DerivedHead that inherits all the functions of the 'class' NewHead. A NewHead object would be stored in Part 1 of a DerivedHead object. For an example, read the original post below.

The thing I can't figure out is how to pattern match on n_NewHead (in Out[2]) . The name of the pattern _NewHead can, in principle, be anything, and the argument list to func is similarly arbitrary.

Any advice is appreciated!

  • Seth

Original post below:


I have read some posts here on object oriented programming as well as many pattern matching posts, but nothing (I have found) seems to address this case, so I thought I'd ask a question.

I have read some posts here on object oriented programming as well as many pattern matching posts, but nothing (I have found) seems to address this case, so I thought I'd ask a question.

Edit:


I think in my original post, I missed emphasizing the main point. This is mainly a pattern matching question. If you're interested in the 'why' of this question, please read the original post below. The short question:

Suppose I have a newly defined, unevaluated Head, called NewHead. I define a function associated with NewHead as (I add in the x & y to emphasize that the argument list can be arbitrary so long as it contains n_NewHead)

In[1]= NewHead /: func[x_, n_NewHead, y_] := n 

This has

In[2]= UpValues[NewHead] Out[2]= {HoldPattern[func[x_, n_NewHead, y_]] :> n} 

I would like to use pattern matching so I can transform this UpValue list like

In[3]= UpValues[NewHead] /. (* Some pattern matching here resulting in: *) Out[3]= {HoldPattern[func[x_, d_DerivedHead, y_]] :> func[x, d[[1]], y]} 

The point is to make a 'class' DerivedHead that inherits all the functions of the 'class' NewHead. A NewHead object would be stored in Part 1 of a DerivedHead object. For an example, read the original post below.

The thing I can't figure out is how to pattern match on n_NewHead (in Out[2]) . The name of the pattern _NewHead can, in principle, be anything, and the argument list to func is similarly arbitrary.

Any advice is appreciated!

  • Seth

Original post below:


I have read some posts here on object oriented programming as well as many pattern matching posts, but nothing (I have found) seems to address this case, so I thought I'd ask a question.

Source Link
shopper
  • 319
  • 1
  • 7

Inheritance in Mathematica using pattern matching on UpValues

I have read some posts here on object oriented programming as well as many pattern matching posts, but nothing (I have found) seems to address this case, so I thought I'd ask a question.

I am trying to implement some features of object oriented programming in Mathematica, most notably inheritance. Imagine I have a polygon class with Head Poly created like

ToPoly[l : {{_, _} ..}] := Module[{}, If[Length@l < 3, Print["Poly object must have at least 3 points"]; Abort[]]; Poly @@ l ] 

It has functions associated with it like (note TagSetDelayed)

distance[{x1_, y1_}, {x2_, y2_}] := Sqrt[(x2 - x1)^2 + (y2 - y1)^2] Poly /: Perimeter[p_Poly] := Module[{pts, ptsShift}, pts = List @@ p; ptsShift = Join[{Last@pts}, Most@pts]; Total@MapThread[distance, {pts, ptsShift}] ] Poly /: Vertices[p_Poly] := Length@p 

Now, I want to create a quadrilateral sub-class with Head Quad. Suppose a Quad can have a color associated with it. So we have

ToQuad[l : {{_, _} ..}, color_String] := Module[{}, If[Length@l =!= 4, Print["Quad object must have exactly 4 points"]; Abort[]]; Quad[ToPoly[l], color] ] Quad /: QuadColor[q_Quad]:=q[[2]] 

At this point, I would like to be able to inherit Perimeter and Vertices from the Poly class. Since they have been defined with TagSetDelayed, I can see those definitions using

UpValues[Poly] (* {HoldPattern[Perimeter[p_Poly]] :> Module[{pts, ptsShift}, pts = List @@ p; ptsShift = Join[{Last[pts]}, Most[pts]]; Total[MapThread[distance, {pts, ptsShift}]]], HoldPattern[Vertices[p_Poly]] :> Length[p]} *) 

Then, I want to define a function that assigns those UpValues to Quad like:

SuperClass[x_]:=x[[1]] DefineDerivedClass[class_,superClass_]:= Module[{}, (* Assign UpValues associated with superClass to class *) ] 

So, after this is called like

DefineDerivedClass[Quad,Poly] 

I would have

UpValues[Quad] (* {HoldPattern[Perimeter[q_Quad]] :> Perimeter[SuperClass[q]], HoldPattern[Vertices[q_Quad]] :> Vertices[SuperClass[q]], HoldPattern[QuadColor[q_Quad]] :> q[[2]]} *) 

The problem is that I cannot figure out the pattern matching to turn the UpValues of Poly into the correct form for Quad for a generic pattern sequence. I can use Part to get inside the HoldPattern, but I cannot match on the p_Poly part. So far, the only way I can figure out to do this is by converting the UpValue expressions into strings, but that is very inelegant. Any ideas?

Thanks,

Seth