On Tue, Apr 7, 2015 at 3:59 PM, Andrew Barnert <abarnert@yahoo.com.dmarc.invalid> wrote:
The mapping is an interesting end-run around the decomposition problem, but it seems like it throws away the type of the object. In other words, Point(x, y) and Vector(x, y) both pattern-match identically to either {'x': x, 'y': y}. In ML or Haskell, distinguishing between the two is one of the key uses of pattern matching.

And another key use is distinguishing Point(0, y), Point(x, 0) and Point(x, y), which it looks like you also can't do this way; the only way to get x bound in the case block (assuming Point, like most classes, isn't iterable and therefore can't be decomposed as a tuple) is to match a dict.

Wouldn't it be better to be explicit about the type matching? For example, using pypatt, I've done this:

In [19]: import pypatt

In [20]: Point = namedtuple('Point', 'x y')

In [21]: @pypatt.transform
def origin_distance(point):
    with match((type(point), point)):
        with (Point, (0, quote(y))):
            return y
        with (Point, (quote(x), 0)):
            return x
        with (Point, (quote(x), quote(y))):
            return (x ** 2 + y ** 2) ** 0.5

In [22]: origin_distance(Point(0, 5))
Out[22]: 5

In [23]: origin_distance(Point(10, 0))
Out[23]: 10

In [24]: origin_distance(Point(3, 4))
Out[24]: 5.0

In [25]: origin_distance(Point(0, 'far'))
Out[25]: 'far'

In [26]: origin_distance(Point('near', 0))
Out[26]: 'near'