Why keep identity-based equality comparison?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • spam.noam@gmail.com

    #1

    Why keep identity-based equality comparison?

    Hello,

    Guido has decided, in python-dev, that in Py3K the id-based order
    comparisons will be dropped. This means that, for example, "{} < []"
    will raise a TypeError instead of the current behaviour, which is
    returning a value which is, really, id({}) < id([]).

    He also said that default equality comparison will continue to be
    identity-based. This means that x == y will never raise an exception,
    as is the situation is now. Here's his reason:
    [color=blue]
    > Let me construct a hypothetical example: suppose we represent a car
    > and its parts as objects. Let's say each wheel is an object. Each
    > wheel is unique and we don't have equivalency classes for them.
    > However, it would be useful to construct sets of wheels (e.g. the set
    > of wheels currently on my car that have never had a flat tire). Python
    > sets use hashing just like dicts. The original hash() and __eq__
    > implementation would work exactly right for this purpose, and it seems
    > silly to have to add it to every object type that could possibly be
    > used as a set member (especially since this means that if a third
    > party library creates objects for you that don't implement __hash__
    > you'd have a hard time of adding it).[/color]

    Now, I don't think it should be so. My reason is basically "explicit is
    better than implicit" - I think that the == operator should be reserved
    for value-based comparison, and raise an exception if the two objects
    can't be meaningfully compared by value. If you want to check if two
    objects are the same, you can always do "x is y". If you want to create
    a set of objects based on their identity (that is, two different
    objects with the same value are considered different elements), you
    have two options:
    1. Create another set type, which is identity-based - it doesn't care
    about the hash value of objects, it just collects references to
    objects. Instead of using set(), you would be able to use, say,
    idset(), and everything would work as wanted.
    2. Write a class like this:

    class Ref(object):
    def __init__(self, obj):
    self._obj = obj
    def __call__(self):
    return self._obj
    def __eq__(self, other):
    return isinstance(othe r, Ref) and self._obj is other._obj
    def __hash__(self):
    return id(self._obj) ^ 0xBEEF

    and use it like this:

    st = set()
    st.add(Ref(whee l1))
    st.add(Ref(whee l2))
    if Ref(wheel1) in st:
    ....
    Those solutions allow the one who writes the class to define a
    value-based comparison operator, and allow the user of the class to
    explicitly state if he wants value-based behaviour or identity-based
    behaviour.

    A few more examples of why this explicit behaviour is good:

    * Things like "Decimal(3. 0) == 3.0" will make more sense (raise an
    exception which explains that decimals should not be compared to
    floats, instead of returning False).
    * You won't be able to use objects as keys, expecting them to be
    compared by value, and causing a bug when they don't. I recently wrote
    a sort-of OCR program, which contains a mapping from a numarray array
    of bits to a character (the array is the pixel-image of the char).
    Everything seemed to work, but the program didn't recognize any
    characters. I discovered that the reason was that arrays are hashed
    according to their identity, which is a thing I had to guess. If
    default == operator were not defined, I would simply get a TypeError
    immediately.
    * It is more forward compatible - when it is discovered that two types
    can sensibly be compared, the comparison can be defined, without
    changing an existing behaviour which doesn't raise an exception.

    My question is, what reasons are left for leaving the current default
    equality operator for Py3K, not counting backwards-compatibility?
    (assume that you have idset and iddict, so explicitness' cost is only
    two characters, in Guido's example)

    Thanks,
    Noam

  • Mike Meyer

    #2
    Re: Why keep identity-based equality comparison?

    spam.noam@gmail .com writes:[color=blue]
    > My question is, what reasons are left for leaving the current default
    > equality operator for Py3K, not counting backwards-compatibility?
    > (assume that you have idset and iddict, so explicitness' cost is only
    > two characters, in Guido's example)[/color]

    Yes. Searching for items in heterogenous containers. With your change
    in place, the "in" operator becomes pretty much worthless on
    containers of heterogenous objects. Ditto for container methods that
    do searches for "equal" members. Whenever you compare two objects that
    don't have the same type, you'll get an exception and terminate the
    search. If the object your searching for would have been found
    "later", you lose - you'll get the wrong answer.

    You could fix this by patching all the appropriate methods. But then
    how do you describe their behavior, without making some people expect
    that it will raise an exception if they pass it incomparable types?

    Also, every container type now has this split between identity and
    equality has to be dealt with for *every* container class. If you want
    identity comparisons on objects, you have to store them in an idlist
    for the in operator and index methods to work properly.

    I also think your basic idea is wrong. The expression "x == y" is
    intuitively False if x and y aren't comparable. I'd say breaking that
    is a bad thing. But if you don't break that, then having "x == y"
    raise an exception for user classes seems wrong. The comparison should
    be False unless they are the same object - which is exactly what
    equality based on id gives us.

    <mike
    --
    Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
    Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

    Comment

    • Giovanni Bajo

      #3
      Re: Why keep identity-based equality comparison?

      Mike Meyer wrote:
      [color=blue][color=green]
      >> My question is, what reasons are left for leaving the current default
      >> equality operator for Py3K, not counting backwards-compatibility?
      >> (assume that you have idset and iddict, so explicitness' cost is only
      >> two characters, in Guido's example)[/color]
      >
      > Yes. Searching for items in heterogenous containers. With your change
      > in place, the "in" operator becomes pretty much worthless on
      > containers of heterogenous objects. Ditto for container methods that
      > do searches for "equal" members. Whenever you compare two objects that
      > don't have the same type, you'll get an exception and terminate the
      > search. If the object your searching for would have been found
      > "later", you lose - you'll get the wrong answer.
      >
      > You could fix this by patching all the appropriate methods. But then
      > how do you describe their behavior, without making some people expect
      > that it will raise an exception if they pass it incomparable types?
      >
      > Also, every container type now has this split between identity and
      > equality has to be dealt with for *every* container class. If you want
      > identity comparisons on objects, you have to store them in an idlist
      > for the in operator and index methods to work properly.
      >
      > I also think your basic idea is wrong. The expression "x == y" is
      > intuitively False if x and y aren't comparable. I'd say breaking that
      > is a bad thing. But if you don't break that, then having "x == y"
      > raise an exception for user classes seems wrong. The comparison should
      > be False unless they are the same object - which is exactly what
      > equality based on id gives us.[/color]

      Seconded. All hell would break loose if Python didn't allow == for heterogenous
      types, $DEITY only knows how many types I relied on it. Please don't let it go
      in Py3k.
      --
      Giovanni Bajo


      Comment

      • Antoon Pardon

        #4
        Re: Why keep identity-based equality comparison?

        Op 2006-01-10, Mike Meyer schreef <mwm@mired.org> :[color=blue]
        > spam.noam@gmail .com writes:[color=green]
        >> My question is, what reasons are left for leaving the current default
        >> equality operator for Py3K, not counting backwards-compatibility?
        >> (assume that you have idset and iddict, so explicitness' cost is only
        >> two characters, in Guido's example)[/color]
        >
        > Yes. Searching for items in heterogenous containers. With your change
        > in place, the "in" operator becomes pretty much worthless on
        > containers of heterogenous objects. Ditto for container methods that
        > do searches for "equal" members. Whenever you compare two objects that
        > don't have the same type, you'll get an exception and terminate the
        > search. If the object your searching for would have been found
        > "later", you lose - you'll get the wrong answer.[/color]

        Maybe that is just a wrong implementation of the "in" operator.

        One may agree on a protocol for the "in" operator to catch the
        TypeError when it tests for equality and treating the raised
        exception the same as the two elements not being equal.
        [color=blue]
        > You could fix this by patching all the appropriate methods. But then
        > how do you describe their behavior, without making some people expect
        > that it will raise an exception if they pass it incomparable types?[/color]

        But that is already a problem. Remember the thread about the Enum
        class which originally raised an exception when comparing values
        from different Enums. This would already cause such a problem.

        There is no way in python now to throw an exception when you
        think comparing your object to some very different object
        is just meaningless and using such an object in a container
        that can be searched via the "in" operator.
        [color=blue]
        > Also, every container type now has this split between identity and
        > equality has to be dealt with for *every* container class. If you want
        > identity comparisons on objects, you have to store them in an idlist
        > for the in operator and index methods to work properly.[/color]
        [color=blue]
        > I also think your basic idea is wrong. The expression "x == y" is
        > intuitively False if x and y aren't comparable.[/color]

        I'm not that sure about the "intuitivel y". The author of the Enum
        class didn't seem to find it that intuitive to just name one
        counter example. IMO "x == y" turning up false when uncomparable
        is just as intuitive as "x < y" turning up false when uncomparable
        but a lot of people don't seem to agree with the latter. My impression
        is that what is intuitive may vary wildly here.

        But there are certainly circumstances that I would prefer 1 == (1,2)
        to throw an exception instead of simply turning up False.

        I would say some more thinking is needed in this area. Now we can
        have weird circumstances where A == B and B == C but A != C.
        I think such cases can be troublesome too for containers and the
        "in" operator.

        IMO some more thinking about this is needed before deciding this
        would be a good idea or not.

        --
        Antoon Pardon

        Comment

        • Mike Meyer

          #5
          Re: Why keep identity-based equality comparison?

          Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=blue][color=green]
          >> Yes. Searching for items in heterogenous containers. With your change
          >> in place, the "in" operator becomes pretty much worthless on
          >> containers of heterogenous objects. Ditto for container methods that
          >> do searches for "equal" members. Whenever you compare two objects that
          >> don't have the same type, you'll get an exception and terminate the
          >> search. If the object your searching for would have been found
          >> "later", you lose - you'll get the wrong answer.[/color]
          > Maybe that is just a wrong implementation of the "in" operator.[/color]

          That's what I said just below:
          [color=blue][color=green]
          >> You could fix this by patching all the appropriate methods. But then
          >> how do you describe their behavior, without making some people expect
          >> that it will raise an exception if they pass it incomparable types?[/color]
          > But that is already a problem. Remember the thread about the Enum
          > class which originally raised an exception when comparing values
          > from different Enums. This would already cause such a problem.[/color]

          Yes, I remember. I also remember that it was eventually agreed that
          that Enum behavior was broken.
          [color=blue]
          > There is no way in python now to throw an exception when you
          > think comparing your object to some very different object
          > is just meaningless and using such an object in a container
          > that can be searched via the "in" operator.[/color]

          I claim that comparing for equality is *never* meaningless. Either two
          objects are equal, or they aren't. It may be that they are of
          different types - like the enum example above - in which case they
          will never compare equal.

          Note that this is different from an ordering. It's possible to have a
          pair of objects - maybe even of the same type - that can't be ordered
          in anyway. In this case, raising an exception when you try that
          comarison makes sense.
          [color=blue][color=green]
          >> Also, every container type now has this split between identity and
          >> equality has to be dealt with for *every* container class. If you want
          >> identity comparisons on objects, you have to store them in an idlist
          >> for the in operator and index methods to work properly.
          >> I also think your basic idea is wrong. The expression "x == y" is
          >> intuitively False if x and y aren't comparable.[/color]
          > But there are certainly circumstances that I would prefer 1 == (1,2)
          > to throw an exception instead of simply turning up False.[/color]

          So what are they?
          [color=blue]
          > I would say some more thinking is needed in this area. Now we can
          > have weird circumstances where A == B and B == C but A != C.[/color]

          Nothing wierd about that at all. Anyone who's dealt with floats at all
          should be used to it.
          [color=blue]
          > I think such cases can be troublesome too for containers and the
          > "in" operator.[/color]

          I don't. Can you provide an example of where it is?
          [color=blue]
          > IMO some more thinking about this is needed before deciding this
          > would be a good idea or not.[/color]

          Actually, what's need are examples of usages where breaking equality
          into two (or more - most LISPs have three different definitions of
          equality) different relations is usefull.

          <mike
          --
          Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
          Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

          Comment

          • Fuzzyman

            #6
            Re: Why keep identity-based equality comparison?

            On 9 Jan 2006 14:40:45 -0800, spam.noam@gmail .com wrote:
            [color=blue]
            >Hello,
            >
            >Guido has decided, in python-dev, that in Py3K the id-based order
            >comparisons will be dropped. This means that, for example, "{} < []"
            >will raise a TypeError instead of the current behaviour, which is
            >returning a value which is, really, id({}) < id([]).
            >
            >He also said that default equality comparison will continue to be
            >identity-based. This means that x == y will never raise an exception,
            >as is the situation is now. Here's his reason:
            >[color=green]
            >> Let me construct a hypothetical example: suppose we represent a car
            >> and its parts as objects. Let's say each wheel is an object. Each
            >> wheel is unique and we don't have equivalency classes for them.
            >> However, it would be useful to construct sets of wheels (e.g. the set
            >> of wheels currently on my car that have never had a flat tire). Python
            >> sets use hashing just like dicts. The original hash() and __eq__
            >> implementation would work exactly right for this purpose, and it seems
            >> silly to have to add it to every object type that could possibly be
            >> used as a set member (especially since this means that if a third
            >> party library creates objects for you that don't implement __hash__
            >> you'd have a hard time of adding it).[/color]
            >
            >Now, I don't think it should be so. My reason is basically "explicit is
            >better than implicit" - I think that the == operator should be reserved
            >for value-based comparison, and raise an exception if the two objects
            >can't be meaningfully compared by value. If you want to check if two
            >objects are the same, you can always do "x is y". If you want to create
            >a set of objects based on their identity (that is, two different
            >objects with the same value are considered different elements), you
            >have two options:[/color]

            I often want to be able to ask, is one object equal to another, where
            they *might* be of the same type or notr.

            If they aren't of the same type, then the answer to :

            a == b

            is obviously False. Otherwise I have to wrap the test in a
            ``try...except` ` block or compare type (and possibly then compare
            value). Both of which are more verbose.

            All the best,

            Fuzzyman
            http://www.voidspace.org.uk/python/index.shtml

            Comment

            • Antoon Pardon

              #7
              Re: Why keep identity-based equality comparison?

              Op 2006-01-10, Mike Meyer schreef <mwm@mired.org> :[color=blue]
              > Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=green][color=darkred]
              >>> You could fix this by patching all the appropriate methods. But then
              >>> how do you describe their behavior, without making some people expect
              >>> that it will raise an exception if they pass it incomparable types?[/color]
              >> But that is already a problem. Remember the thread about the Enum
              >> class which originally raised an exception when comparing values
              >> from different Enums. This would already cause such a problem.[/color]
              >
              > Yes, I remember. I also remember that it was eventually agreed that
              > that Enum behavior was broken.[/color]

              It is broken in the context of the current python behaviour.
              In a different context with different behaviour of containers
              such behaviour may very well be the most intuitive.

              We are now talking about python3k and so such we should
              be open to the possibility that what is broken in
              current python may very well be desirable behaviour for
              what python will evolve into.
              [color=blue][color=green]
              >> There is no way in python now to throw an exception when you
              >> think comparing your object to some very different object
              >> is just meaningless and using such an object in a container
              >> that can be searched via the "in" operator.[/color]
              >
              > I claim that comparing for equality is *never* meaningless. Either two
              > objects are equal, or they aren't. It may be that they are of
              > different types - like the enum example above - in which case they
              > will never compare equal.
              >
              > Note that this is different from an ordering. It's possible to have a
              > pair of objects - maybe even of the same type - that can't be ordered
              > in anyway. In this case, raising an exception when you try that
              > comarison makes sense.[/color]

              IMO you have the choice between taking the mathematical route or
              the practical route.

              If you take the first choice you are right that comparing for
              equality is never meaningless, but so is using the other comparisons.
              If two objects are not comparable then we just have that a < b, a ==b
              and a > b are all false.

              Now you can take the practical option and decide that programmaticall y
              it make no sense to compare a specific couple of values and throw an
              exception in this case, but it doesn't matter much which test you are
              conducting at that point.

              Maybe python should adopt both approaches and introduce a new family
              of comparators. Then one family will always succeed and the other
              family can throw an exception.
              [color=blue][color=green][color=darkred]
              >>> Also, every container type now has this split between identity and
              >>> equality has to be dealt with for *every* container class. If you want
              >>> identity comparisons on objects, you have to store them in an idlist
              >>> for the in operator and index methods to work properly.
              >>> I also think your basic idea is wrong. The expression "x == y" is
              >>> intuitively False if x and y aren't comparable.[/color]
              >> But there are certainly circumstances that I would prefer 1 == (1,2)
              >> to throw an exception instead of simply turning up False.[/color]
              >
              > So what are they?
              >[color=green]
              >> I would say some more thinking is needed in this area. Now we can
              >> have weird circumstances where A == B and B == C but A != C.[/color]
              >
              > Nothing wierd about that at all. Anyone who's dealt with floats at all
              > should be used to it.[/color]

              With floats that is entirely a problem of precision. When you are
              working with discrete types such circumstances remain weird.
              [color=blue][color=green]
              >> I think such cases can be troublesome too for containers and the
              >> "in" operator.[/color]
              >
              > I don't. Can you provide an example of where it is?[/color]

              Well not with the "in" operator but with the index method of lists
              which seems related enough.

              If the "in" operator returns true one can use index to find out
              an element in the container that compares equal. Now normally
              it wouldn't make a difference whether you would make further
              comparisons against the original object or against the object
              in the list. But in this case it can make a difference and
              it isn't obvious what one should do.
              [color=blue][color=green]
              >> IMO some more thinking about this is needed before deciding this
              >> would be a good idea or not.[/color]
              >
              > Actually, what's need are examples of usages where breaking equality
              > into two (or more - most LISPs have three different definitions of
              > equality) different relations is usefull.[/color]

              I think it is usefull because when I am looking for 1 in a list,
              I'm not necessarily happy when I find 1.0 or decimal("1").

              --
              Antoon Pardon

              Comment

              • Antoon Pardon

                #8
                Re: Why keep identity-based equality comparison?

                Op 2006-01-10, Fuzzyman schreef <fuzzyman_no@sp am_voidspace.or g.uk>:[color=blue]
                > On 9 Jan 2006 14:40:45 -0800, spam.noam@gmail .com wrote:
                >[color=green]
                >>Hello,
                >>
                >>Guido has decided, in python-dev, that in Py3K the id-based order
                >>comparisons will be dropped. This means that, for example, "{} < []"
                >>will raise a TypeError instead of the current behaviour, which is
                >>returning a value which is, really, id({}) < id([]).
                >>
                >>He also said that default equality comparison will continue to be
                >>identity-based. This means that x == y will never raise an exception,
                >>as is the situation is now. Here's his reason:
                >>[color=darkred]
                >>> Let me construct a hypothetical example: suppose we represent a car
                >>> and its parts as objects. Let's say each wheel is an object. Each
                >>> wheel is unique and we don't have equivalency classes for them.
                >>> However, it would be useful to construct sets of wheels (e.g. the set
                >>> of wheels currently on my car that have never had a flat tire). Python
                >>> sets use hashing just like dicts. The original hash() and __eq__
                >>> implementation would work exactly right for this purpose, and it seems
                >>> silly to have to add it to every object type that could possibly be
                >>> used as a set member (especially since this means that if a third
                >>> party library creates objects for you that don't implement __hash__
                >>> you'd have a hard time of adding it).[/color]
                >>
                >>Now, I don't think it should be so. My reason is basically "explicit is
                >>better than implicit" - I think that the == operator should be reserved
                >>for value-based comparison, and raise an exception if the two objects
                >>can't be meaningfully compared by value. If you want to check if two
                >>objects are the same, you can always do "x is y". If you want to create
                >>a set of objects based on their identity (that is, two different
                >>objects with the same value are considered different elements), you
                >>have two options:[/color]
                >
                > I often want to be able to ask, is one object equal to another, where
                > they *might* be of the same type or notr.
                >
                > If they aren't of the same type, then the answer to :
                >
                > a == b
                >
                > is obviously False. Otherwise I have to wrap the test in a
                > ``try...except` ` block or compare type (and possibly then compare
                > value). Both of which are more verbose.[/color]

                If we are going to stick to one equal comparator then there will
                always be cases that seem to be more verbose than needed. In the
                case where you consider it an error if you are working with objects
                of different classes you now have to expicitely test for unequal
                types and raise an exception explicitly which is also more verbose.

                IMO if they aren't of the same type then the answer to:

                a < b

                is just as obviously False as

                a == b

                Yet how things are proposed now, the first will throw an exception
                and the latter will return False.

                --
                Antoon Pardon

                Comment

                • Peter Decker

                  #9
                  Re: Why keep identity-based equality comparison?

                  On 10 Jan 2006 13:33:20 GMT, Antoon Pardon <apardon@forel. vub.ac.be> wrote:
                  [color=blue]
                  > IMO if they aren't of the same type then the answer to:
                  >
                  > a < b
                  >
                  > is just as obviously False as
                  >
                  > a == b
                  >
                  > Yet how things are proposed now, the first will throw an exception
                  > and the latter will return False.[/color]

                  I don't see the two comparisons as equivalent at all. If two things
                  are different, it does not follow that they can be ranked. If we have
                  two objects, such as a spark plug and a cam shaft, it is one thing to
                  say that the two are not the same object; it is quite another to say
                  that one is 'greater than' or 'less than' the other.

                  --

                  # p.d.

                  Comment

                  • Antoon Pardon

                    #10
                    Re: Why keep identity-based equality comparison?

                    Op 2006-01-10, Peter Decker schreef <pydecker@gmail .com>:[color=blue]
                    > On 10 Jan 2006 13:33:20 GMT, Antoon Pardon <apardon@forel. vub.ac.be> wrote:
                    >[color=green]
                    >> IMO if they aren't of the same type then the answer to:
                    >>
                    >> a < b
                    >>
                    >> is just as obviously False as
                    >>
                    >> a == b
                    >>
                    >> Yet how things are proposed now, the first will throw an exception
                    >> and the latter will return False.[/color]
                    >
                    > I don't see the two comparisons as equivalent at all. If two things
                    > are different, it does not follow that they can be ranked.[/color]

                    That a < b returns false doesn't imply that a and b can be ranked.
                    take sets. set([1,2]) and set([1,3)) can't be ranked but
                    set([1,2]) < set([1,3)) returns False just as set([1,2]) > set([1,3))
                    does.
                    [color=blue]
                    > If we have
                    > two objects, such as a spark plug and a cam shaft, it is one thing to
                    > say that the two are not the same object; it is quite another to say
                    > that one is 'greater than' or 'less than' the other.[/color]

                    But we don't say the latter. What we do say is that one is 'not greater
                    than' and 'not lesser than' (and 'not equal to') the other.

                    --
                    Antoon Pardon

                    Comment

                    • Christopher Subich

                      #11
                      Re: Why keep identity-based equality comparison?

                      Antoon Pardon wrote:[color=blue]
                      > Op 2006-01-10, Peter Decker schreef <pydecker@gmail .com>:[/color]
                      [color=blue][color=green]
                      >>I don't see the two comparisons as equivalent at all. If two things
                      >>are different, it does not follow that they can be ranked.[/color]
                      >
                      >
                      > That a < b returns false doesn't imply that a and b can be ranked.
                      > take sets. set([1,2]) and set([1,3)) can't be ranked but
                      > set([1,2]) < set([1,3)) returns False just as set([1,2]) > set([1,3))
                      > does.[/color]

                      Breaking my resolution already, but you're ignoring the fact that the
                      set type uses the '<' and '>' operators from a set-theoretic, not
                      number-theoretic point of view. Saying "set(1,3) is greater than
                      set(1,2)" is meaningless (and not false), because the mathematical basis
                      of the operator in this context is superset -- "set(1,3) is a superset
                      of set(1,2)" is well-defined and false.

                      Set uses '<' and '>' because the superset and subset symbols aren't on
                      the keyboard.

                      In languages that allow operator overloading, there are always some
                      well-defined cases where the operator is the simplest, clearest notation
                      yet the operator has a meaning very distinct from the arithmetical
                      operation. As another example, Pyparsing uses '<<' to "load" a Forward
                      declaration, for recursive grammars -- this obviously has nothing to do
                      with bit-shifting.

                      Of course, cases like these two are fairly textbook examples for the
                      argument that operator overloading is unclear; Python accepts the
                      occasional ambiguity and allows (indeed encourages, to a reasonable
                      degree) operator overloading for conciseness and expressiveness.


                      To reply to your other argument, Antoon:[color=blue]
                      > Maybe python should adopt both approaches and introduce a new family
                      > of comparators. Then one family will always succeed and the other
                      > family can throw an exception.[/color]
                      [snip][color=blue]
                      > I think it is usefull because when I am looking for 1 in a list,
                      > I'm not necessarily happy when I find 1.0 or decimal("1").[/color]


                      I personally feel that the use cases for this "other" comparison (===?)
                      are very restricted. In fact, your example itself isn't even a use-case
                      for this operator, because integer/float/decimal have well-defined
                      equality comparisons already (that explicitly account for different
                      types) -- the implicit "not is implies !=, if __eq__ isn't defined"
                      behaviour isn't triggered.

                      The use-case for a "===" operator would seem to be restricted to when
                      program behaviour is determined soley by "a" not equalling "b." If a
                      "wrong" object is referenced by "b," then the program might do a Bad
                      Thing, because it expects "b" to be something else... except that the
                      error would be caught later anyway -- probably by calling "b.method() "
                      or somesuch.

                      In fact, even in more esoteric cases the behaviour of "==" as-is is
                      useful; in the itertools.izip_ longest discussion, this behaviour is
                      implicitly used in the sentinel-stopping method
                      (izip(chain(ite r,sent),chain(i ter,sent),...,s top=(sent,sent, sent,...)),
                      to badly mangle the syntax).

                      Comment

                      • Fuzzyman

                        #12
                        Re: Why keep identity-based equality comparison?


                        Peter Decker wrote:[color=blue]
                        > On 10 Jan 2006 13:33:20 GMT, Antoon Pardon <apardon@forel. vub.ac.be> wrote:
                        >[color=green]
                        > > IMO if they aren't of the same type then the answer to:
                        > >
                        > > a < b
                        > >
                        > > is just as obviously False as
                        > >
                        > > a == b
                        > >
                        > > Yet how things are proposed now, the first will throw an exception
                        > > and the latter will return False.[/color]
                        >
                        > I don't see the two comparisons as equivalent at all. If two things
                        > are different, it does not follow that they can be ranked. If we have
                        > two objects, such as a spark plug and a cam shaft, it is one thing to
                        > say that the two are not the same object; it is quite another to say
                        > that one is 'greater than' or 'less than' the other.
                        >[/color]

                        I agree.

                        If a and b are of incomparable types, then a != b is True but a < b is
                        meaningless.

                        All the best,

                        Fuzzyman
                        http://www.voidspace.org.uk/python/index.shtml

                        [color=blue]
                        > --
                        >
                        > # p.d.[/color]

                        Comment

                        • Mike Meyer

                          #13
                          Re: Why keep identity-based equality comparison?

                          Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=blue][color=green][color=darkred]
                          >>> There is no way in python now to throw an exception when you
                          >>> think comparing your object to some very different object
                          >>> is just meaningless and using such an object in a container
                          >>> that can be searched via the "in" operator.[/color]
                          >> I claim that comparing for equality is *never* meaningless. Either two
                          >> objects are equal, or they aren't. It may be that they are of
                          >> different types - like the enum example above - in which case they
                          >> will never compare equal.
                          >> Note that this is different from an ordering. It's possible to have a
                          >> pair of objects - maybe even of the same type - that can't be ordered
                          >> in anyway. In this case, raising an exception when you try that
                          >> comarison makes sense.[/color]
                          > IMO you have the choice between taking the mathematical route or
                          > the practical route.[/color]

                          The behavior proposed for Py3k *is* the practical route. It gives a
                          reasonable behavior, and one that leads to simple implemenations for
                          container operations.
                          [color=blue]
                          > Now you can take the practical option and decide that programmaticall y
                          > it make no sense to compare a specific couple of values and throw an
                          > exception in this case, but it doesn't matter much which test you are
                          > conducting at that point.[/color]

                          Can you provide a case where having a test for equality throw an
                          exception is actually useful?

                          BTW, the case you're arguing for is *different* from the case the OP
                          proposed. By my reading, he wanted equality testing to throw an
                          exception for two objects unless a comparison was explicitly coded. So
                          that even a == a could cause an exception.
                          [color=blue]
                          > Maybe python should adopt both approaches and introduce a new family
                          > of comparators. Then one family will always succeed and the other
                          > family can throw an exception.[/color]

                          Comparators - including equality comparators - can already throw
                          exceptions. The enum case proved that.
                          [color=blue][color=green][color=darkred]
                          >>>> Also, every container type now has this split between identity and
                          >>>> equality has to be dealt with for *every* container class. If you want
                          >>>> identity comparisons on objects, you have to store them in an idlist
                          >>>> for the in operator and index methods to work properly.
                          >>>> I also think your basic idea is wrong. The expression "x == y" is
                          >>>> intuitively False if x and y aren't comparable.
                          >>> But there are certainly circumstances that I would prefer 1 == (1,2)
                          >>> to throw an exception instead of simply turning up False.[/color]
                          >> So what are they?[/color][/color]

                          Again - give us real use cases.
                          [color=blue][color=green][color=darkred]
                          >>> I would say some more thinking is needed in this area. Now we can
                          >>> have weird circumstances where A == B and B == C but A != C.[/color]
                          >> Nothing wierd about that at all. Anyone who's dealt with floats at all
                          >> should be used to it.[/color]
                          > With floats that is entirely a problem of precision. When you are
                          > working with discrete types such circumstances remain weird.[/color]

                          Floats *are* a discrete type. The equality *relationship* is what's
                          fuzzy. There are lots of non-transitive relationships around. I don't
                          find them wierd at all.
                          [color=blue][color=green][color=darkred]
                          >>> I think such cases can be troublesome too for containers and the
                          >>> "in" operator.[/color]
                          >> I don't. Can you provide an example of where it is?[/color]
                          > Well not with the "in" operator but with the index method of lists
                          > which seems related enough.[/color]

                          The index method of list is already a bit fuzzy.
                          [color=blue]
                          > If the "in" operator returns true one can use index to find out
                          > an element in the container that compares equal. Now normally
                          > it wouldn't make a difference whether you would make further
                          > comparisons against the original object or against the object
                          > in the list. But in this case it can make a difference and
                          > it isn't obvious what one should do.[/color]

                          That's because in this case there's no on "right" answer. What you
                          should do will depend on what you are trying to accomplish. That's the
                          normal state of affairs when programming.
                          [color=blue][color=green][color=darkred]
                          >>> IMO some more thinking about this is needed before deciding this
                          >>> would be a good idea or not.[/color]
                          >> Actually, what's need are examples of usages where breaking equality
                          >> into two (or more - most LISPs have three different definitions of
                          >> equality) different relations is usefull.[/color]
                          > I think it is usefull because when I am looking for 1 in a list,
                          > I'm not necessarily happy when I find 1.0 or decimal("1").[/color]

                          That's an argument for a more *precise* equality operator. That's
                          certainly worth considering, but has nothing to do with whether or not
                          it makes sense for an equality comparison to throw an exception.

                          <mike
                          --
                          Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
                          Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

                          Comment

                          • spam.noam@gmail.com

                            #14
                            Re: Why keep identity-based equality comparison?

                            > Can you provide a case where having a test for equality throw an > exception is actually useful? Yes. It will be useful because: 1. The bug of not finding a key in a dict because it was implicitly hashed by identity and not by value, would not have happened. 2. You wouldn't get the weird 3.0 != Decimal("3.0") - you'll get an exception which explains that these types aren't comparable. 3. If, in some time, you will decide that float and Decimal could be compared, you will be able to implement that without being concerned about backwards compatibility issues. >>>> But there are certainly circumstances that I would prefer 1 == (1,2) >>>> to throw an exception instead of simply turning up False. >>> So what are they? > > Again - give us real use cases. You may catch bugs earlier - say you have a multidimensiona l array, and you forgot one index. Having comparison raise an exception because type comparison is meaningless, instead of returning False silently, will help you catch your problem earlier. Noam

                            Comment

                            • spam.noam@gmail.com

                              #15
                              Re: Why keep identity-based equality comparison?

                              It seems to me that both Mike's and Fuzzyman's objections were that
                              sometimes you want the current behaviour, of saying that two objects
                              are equal if they are: 1. the same object or 2. have the same value
                              (when it's meaningful). In both cases this can be accomplished pretty
                              easily: You can do it with a try..except block, and you can write the
                              try...except block inside the __contains__ method. (It's really pretty
                              simple: try: return a == b except TypeError: return a is b )
                              Also, Mike said that you'll need an idlist object too - and I think
                              he's right and that there's nothing wrong with it. Note that while you
                              can easily define the current == behaviour using the proposed
                              behaviour, you can't define the proposed behaviour using the current
                              behaviour. Also note that using the current behaviour, you can't easily
                              treat objects that do define a meaningful value comparison, by
                              identity. Also note that in the cases that you do want identity-based
                              behaviour, defining it explicitly can result in a more efficient
                              program: explicit identity-based dict doesn't have to call any __hash__
                              and __eq__ protocols - it can compare the pointers themselves. The same
                              if you want to locate a specific object in a list - use the proposed
                              idlist and save yourself O(n) value-based comparisons, which might be
                              heavy. Noam

                              Comment

                              Working...