[PEP draft 2] Adding new math operators

Rainer Deyke root at rainerdeyke.com
Wed Aug 9 00:52:04 EDT 2000


"Huaiyu Zhu" <hzhu at localhost.localdomain> wrote in message
news:slrn8p1e12.1ob.hzhu at rocket.knowledgetrack.com...
> Well, conceptually, two sets of operators are equally fundamental: the
> arithmetic type operators + - * / and the lattice type operators (and)
(or)
> (not) (xor), etc.  Both of them have two versions, objectwise and
> elementwise. The bitwise operators are elementwise lattice operators when
> each bit in an integer is regarded as an element.

I've mentioned this before: your division between objectwise and elementwise
operators does not hold because it is not clear whether elementwise
operators are "deep" or "shallow".  For example ([[0, 1], [2, 3]]
(elementwise+) [[4, 5], [6, 7]]) could evaluate to either [[4, 6], [8, 10]]
or [[0, 1, 4, 5], [2, 3, 6, 7]].

The only truly flexible approach would be to allow users to specify an
arbitrary depth for elementwise operators.  In the proposed ~* notation,
that would mean that for every binary operator X there is an operator ~X
which goes one level deeper than X - even if X itself is ~~+.  (This makes
the proposed notation useless unless someone figures out how support an
infinite number of operators.)

Another problem with naive elementwise operators is that they require a
ridiculous number of __magic__ functions, all of which are essentially
identical.  For example:

class Pair:
  def __init__(self, first, second):
    self.first = first
    self.second = second

  def __elementwise_add__(self, other):
    return Pair(self.first + other.first, self.second + other.second)

  def __elementwise_multiply__(self, other):
    return Pair(self.first * other.first, self.second * other.second)

  def __elementwise_subtract__(self, other):
    return Pair(self.first - other.first, self.second - other.second)

  def __elementwise_divide__(self, other):
    return Pair(self.first / other.first, self.second / other.second)

  def __elementwise_fnord__(self, other):
    return Pair(fnord(self.first,other.first),
fnord(self.second,other.second)

  def __elementwise_call__(self, other):
    return Pair(self.first(other.first), self.second(other.second))

  def __elementwise_elementwise_add__(self, other):
    return Pair(self.first ~+ other.first, self.second ~+ other.second)

  ...

A better solution would be to have a method for "elementwise" operations:

class Pair:
  def __init__(self, first, second):
    self.first = first
    self.second = second

  def elementwise(self, operation):
    return Pair(operation(self.first), operation(self.second))

Alternately, you could add another argument to other __magic__ functions:

class Pair:
  def __init__(self, first, second):
    self.first = first
    self.second = second

  def __add__(self, rhs, depth):
    if (depth == 0):
      return objectwise_add(self, rhs)
    else:
      return Pair(add(self.first, rhs.first, depth - 1),\
        add(self.second, rhs.second, depth - 1)
        # Substitute proper infix syntax for add.


--
Rainer Deyke (root at rainerdeyke.com)
Shareware action/role-playing games      -      http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor





More information about the Python-list mailing list