Attack a sacred Python Cow

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Terry Reedy

    Re: Boolean tests [was Re: Attack a sacred Python Cow]



    Carl Banks wrote:
    >As I wrote in the second reply email I sent, check out my integer set
    >recipe on ASPN (and to save you the search: http://code.activestate.com/recipes/466286/).
    >
    Couple points:
    >
    1. Any container type that returns a length that isn't exactly the
    number of elements in it is broken.
    2. The need for __nonzero__ in this case depends on a limitation in
    the language.
    3. On the other hand, I will concede that sometimes calculating len is
    a lot more expensive than determining emptiness, and at a basic level
    it's important to avoid these costs. You have found a practical use
    case for __nonzero__.
    I thought of another one: testing whether an iterator is 'empty' (will
    raise StopIteration on the next next() (3.0) call) or not. As virtual
    collections, iterators generally have neither __len__ or __bool__. But
    __bool__ (but only __bool__) can be added to any iterator by wrapping it
    with something like the following 3.0 code (not tested):

    class look_ahead_it() :
    def __init__(self, iterable):
    self.it = iter(iterable)
    self.fill_next( )

    def __iter__(self):
    return self
    def __next__(self):
    tem = self.next
    if tem is self.empty:
    raise StopIteration
    else:
    self.fill_next( )
    return tem

    empty = object()
    def fill_next(self)
    try:
    self.next = next(self.it)
    except StopIteration:
    self.next = self.empty

    def __bool__(self):
    return self.next is not self.empty


    Comment

    • Carl Banks

      Re: Boolean tests [was Re: Attack a sacred Python Cow]

      On Jul 29, 10:23 pm, Erik Max Francis <m...@alcyone.c omwrote:
      Carl Banks wrote:
      Bzzt. "if len(x)!=0" is a simple explicit that would work for this
      class and all built-in containers. (Or should--Steven D'Aprano's
      objections notwithstanding , any reasonable container type should
      support this invariant. From a language design standpoint, an "empty"
      builtin could have been created to simplify this even more, but since
      there isn't one len(x)!=0 will have to do.)
      >
      That you choose not to test for non-emptiness doesn't change the fact
      that it's already a builtin part of the language that is supported by
      all fundamental types and is overridable by anyone writing a custom
      type. Use it or don't use it, but it's an example of precisely what you
      were asking for that is both practical and already in widespread use.
      That's not what I was asking for. I was asking for a use case for "if
      x" that can't be replaced by a simple explicit test. Your example
      didn't satisfy that.


      Carl Banks

      Comment

      • Erik Max Francis

        Re: Boolean tests [was Re: Attack a sacred Python Cow]

        Carl Banks wrote:
        That's not what I was asking for. I was asking for a use case for "if
        x" that can't be replaced by a simple explicit test. Your example
        didn't satisfy that.
        It's a completely artificial request. "if x" _is_ a completely simple
        test. Simpler, in fact, than the ones you were advocating.

        --
        Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
        San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
        An ounce of hypocrisy is worth a pound of ambition.
        -- Michael Korda

        Comment

        • Carl Banks

          Re: Boolean tests [was Re: Attack a sacred Python Cow]

          On Jul 29, 7:30 pm, Steven D'Aprano <st...@REMOVE-THIS-
          cybersource.com .auwrote:
          On Tue, 29 Jul 2008 10:30:43 -0700, Carl Banks wrote:
          On Jul 29, 5:15 am, Heiko Wundram <modeln...@mode lnine.orgwrote:
          I can't dig up a simple example from code I wrote quickly, but because
          of the fact that explicit comparisons always hamper polymorphism
          >
          I'm not going to take your word for it. Do you have code that
          demonstrates how "if x" improves polymorphism relative to simple
          explicit tests?
          >
          On the rapidly decreasing chance that you're not trolling (looking more
          and more unlikely every time you post):
          >
          # The recommended way:
          if x:
          do_something
          >
          # Carl's so-called "simple explicit tests" applied to polymorphic code:
          No, the following isn't my way.

          try:
          # could be a sequence or mapping?
          # WARNING: must do this test *before* the number test, otherwise
          # "if [] != 0" will return True, leading to the wrong branch being
          # taken.
          if len(x) != 0:
          do_something
          except AttributeError:
          # not a sequence or mapping, maybe it's a number of some sort
          try:
          int(x)
          except TypeError:
          # not convertable to numbers
          # FIXME: not really sure what to do here for arbitrary types
          # so fall back on converting to a boolean, and hope that works
          if bool(x):
          do_something
          else:
          if x != 0:
          do_something
          I say that you will never, ever have to do this because there isn't a
          do_something that's actually useful for all these types.

          Ok, tell me, oh indignant one, what is do_something? What could
          possibly be the contents of do_something such that it actually does
          something useful? If you can tell me what do_something is you will
          have answered my question.


          Carl Banks

          Comment

          • Carl Banks

            Re: Boolean tests [was Re: Attack a sacred Python Cow]

            On Jul 30, 12:22 am, Erik Max Francis <m...@alcyone.c omwrote:
            Carl Banks wrote:
            That's not what I was asking for. I was asking for a use case for "if
            x" that can't be replaced by a simple explicit test. Your example
            didn't satisfy that.
            >
            It's a completely artificial request.
            Bull. This is a request, that, if satisfied, would prove that "if x"
            is more polymorphic than a simple explicit test. I posed the question
            precisely to see if anyone could come up with a use case that shows
            this benefit of "if x".

            "if x" _is_ a completely simple
            test. Simpler, in fact, than the ones you were advocating.
            It's not explicit.

            Here's what we know for sure.
            1. "if x" uses fewer keystrokes than an explicit test
            2. "if x" creates fewer nodes in the parse tree than an explicit test
            3. Couple minor things we somehow managed to uncover in this thread

            Is that it? Is that all the benefits of "if x"? This is what I want
            to establish. A bunch of people in this thread are crowing that it
            helps polymorphism, but I have only seen minor examples of it.

            I've explained why I doubt that it helps polymorphism that much: you
            almost never see code for which an integer and list both work, so
            having the ability to spell a test the same way for both types isn't
            useful. If you claim that "if x" does help polymorphism, please tell
            me what's wrong with the above analysis.

            Or just give me the use case I asked for.


            Carl Banks

            Comment

            • Carl Banks

              Re: Boolean tests [was Re: Attack a sacred Python Cow]

              On Jul 29, 11:17 pm, Terry Reedy <tjre...@udel.e duwrote:
              Carl Banks wrote:
              As I wrote in the second reply email I sent, check out my integer set
              recipe on ASPN (and to save you the search: http://code.activestate.com/recipes/466286/).
              >
              Couple points:
              >
              1. Any container type that returns a length that isn't exactly the
              number of elements in it is broken.
              2. The need for __nonzero__ in this case depends on a limitation in
              the language.
              3. On the other hand, I will concede that sometimes calculating len is
              a lot more expensive than determining emptiness, and at a basic level
              it's important to avoid these costs. You have found a practical use
              case for __nonzero__.
              >
              I thought of another one: testing whether an iterator is 'empty' (will
              raise StopIteration on the next next() (3.0) call) or not. As virtual
              collections, iterators generally have neither __len__ or __bool__. But
              __bool__ (but only __bool__) can be added to any iterator by wrapping it
              with something like the following 3.0 code (not tested):
              >
              class look_ahead_it() :
              def __init__(self, iterable):
              self.it = iter(iterable)
              self.fill_next( )
              >
              def __iter__(self):
              return self
              def __next__(self):
              tem = self.next
              if tem is self.empty:
              raise StopIteration
              else:
              self.fill_next( )
              return tem
              >
              empty = object()
              def fill_next(self)
              try:
              self.next = next(self.it)
              except StopIteration:
              self.next = self.empty
              >
              def __bool__(self):
              return self.next is not self.empty
              Iterators are funny: if there's any reason you should not use "if x"
              it's because of them. Built-in iterators are always true, so if
              you're writing a function that accepts an iterable you should never
              use the "if x" to test whether it's empty, because it fails for a
              whole class of iterables.

              However, given that that wart exists, your example does work for "if
              x" and not with "if len(x)!=0".

              Then again, it really only works to accommodate faulty code, because
              no code that expects an iterable should be using that test in the
              first place. (Unless you wrap every iterable as soon as you get it,
              but then you're not bound to use __nonzero__.)


              Carl Banks

              Comment

              • Russ P.

                Re: Boolean tests [was Re: Attack a sacred Python Cow]

                On Jul 29, 9:52 pm, Carl Banks <pavlovevide... @gmail.comwrote :
                On Jul 29, 11:17 pm, Terry Reedy <tjre...@udel.e duwrote:
                >
                >
                >
                Carl Banks wrote:
                >As I wrote in the second reply email I sent, check out my integer set
                >recipe on ASPN (and to save you the search: http://code.activestate.com/recipes/466286/).
                >
                Couple points:
                >
                1. Any container type that returns a length that isn't exactly the
                number of elements in it is broken.
                2. The need for __nonzero__ in this case depends on a limitation in
                the language.
                3. On the other hand, I will concede that sometimes calculating len is
                a lot more expensive than determining emptiness, and at a basic level
                it's important to avoid these costs. You have found a practical use
                case for __nonzero__.
                >
                I thought of another one: testing whether an iterator is 'empty' (will
                raise StopIteration on the next next() (3.0) call) or not. As virtual
                collections, iterators generally have neither __len__ or __bool__. But
                __bool__ (but only __bool__) can be added to any iterator by wrapping it
                with something like the following 3.0 code (not tested):
                >
                class look_ahead_it() :
                def __init__(self, iterable):
                self.it = iter(iterable)
                self.fill_next( )
                >
                def __iter__(self):
                return self
                def __next__(self):
                tem = self.next
                if tem is self.empty:
                raise StopIteration
                else:
                self.fill_next( )
                return tem
                >
                empty = object()
                def fill_next(self)
                try:
                self.next = next(self.it)
                except StopIteration:
                self.next = self.empty
                >
                def __bool__(self):
                return self.next is not self.empty
                >
                Iterators are funny: if there's any reason you should not use "if x"
                it's because of them. Built-in iterators are always true, so if
                you're writing a function that accepts an iterable you should never
                use the "if x" to test whether it's empty, because it fails for a
                whole class of iterables.
                >
                However, given that that wart exists, your example does work for "if
                x" and not with "if len(x)!=0".
                >
                Then again, it really only works to accommodate faulty code, because
                no code that expects an iterable should be using that test in the
                first place. (Unless you wrap every iterable as soon as you get it,
                but then you're not bound to use __nonzero__.)
                >
                Carl Banks
                All this discussion about "if x" has me wondering. I use it all the
                time because a fully explicit test just seems redundant. But maybe it
                does have some value in terms of readability and type checking. After
                all, it is possible to forget whether something is a number or a list.

                Having said that, it would sure be nice to be able to write

                if myList is not empty:

                instead of

                if len(myList) != 0:

                Comment

                • Carl Banks

                  Re: Boolean tests [was Re: Attack a sacred Python Cow]

                  On Jul 29, 6:42 pm, Matthew Fitzgibbons <eles...@nienna .orgwrote:
                  Carl Banks wrote:
                  Much like in Steven D'Aprano's example, still the only actual code
                  snippet I've seen, it seems that this can easily be done with a simple
                  explicit test by having all no-advance filters return None and testing
                  with "if x is not None". So it doesn't pass my criterion of being not
                  replaceable with simple explicit test.
                  >
                  Maybe that's not workable for some reason. Perhaps if you'd post a
                  code example that shows this, rather than just talking about it, you
                  might be more persuasive.
                  >>
                  The no-advance filters have to return the object because I don't just
                  forget about it; I evaluate whether I pass it to the next filter or drop
                  it in a completely different queue for use in the next stage of the
                  operation. True means 'I'm ready to move on to the next stage,' False
                  means 'Do the filter thing some more.'
                  I think I see what you're saying, and yeah I guess that could really
                  take advantage of polymorphism between very different types.
                  Furthermore, the argument that I should just change my API to make a
                  'simple test' work is not very convincing.
                  I wasn't suggesting you change it: I was trying to ascertain whether
                  it would have suffered much if you had written it with explicit tests
                  in the first place, or if Python didn't even have magical booleans.
                  The natural, obvious way for
                  a filter to work is to pass through the data it operates on; why on
                  Earth would it return None? I want to DO something with the data. In
                  this case, make a decision about where to pass the data next.
                  If you don't mind me asking: what do you do actually DO with a zero or
                  empty list?
                  In Java,
                  to accomplish this I would have to do lots of introspection and value
                  checking (adding more any time I came up with a new kind of input), or
                  make a new kind of interface that gives me a method so I can do a
                  'simple test' (including wrappers for ints and arrays and anything else
                  I decide to pass in down the road). But Python supports duck typing and
                  gives me a handy __nonzero__ method; I can rebind __nonzero__ in my
                  filters for my own classes, and ints and lists are handled how I want
                  them to be by default. So why jump through hoops instead of just using
                  'if x'?
                  Ah, so it's just happens to work. Still, just happening to work
                  works. (shrug)
                  I don't have any postable code (it's in a half way state and I haven't
                  touched it for a while), but I'll see if I can't find the time to bang
                  something up to give you the gist.
                  I wouldn't bother at this point. I was looking to see if someone
                  could come up with something to disprove my belief on the polymorphic
                  uselessness of "if x" relative to explicit tests, and if (as I
                  anticipated) they did not, I could claim that "if x" is really just a
                  glorified keystroke saver. But I now realize that the failure of this
                  bunch doesn't prove anything. I don't think most people even realize
                  why answering the question I asked would demonstrate the usefulness of
                  "if x".

                  Your example isn't exactly the smoking gun I was looking for, but I
                  guess we'll have to admit that at least one usage will suffer for not
                  having it.


                  Carl Banks

                  Comment

                  • Carl Banks

                    Re: Boolean tests [was Re: Attack a sacred Python Cow]

                    On Jul 30, 1:15 am, "Russ P." <Russ.Paie...@g mail.comwrote:
                    All this discussion about "if x" has me wondering. I use it all the
                    time because a fully explicit test just seems redundant. But maybe it
                    does have some value in terms of readability and type checking. After
                    all, it is possible to forget whether something is a number or a list.
                    IMO, the only time I think "if x" is really dangerous is if you are
                    using "if x" instead of "if x is None" to distinguish between None and
                    a type that can have false values. Well, also it can backfire to use
                    "if x" to check whether an iterable is empty since you can get a false
                    positive if it's an iterator.

                    Other than that it's maybe slighly less type safe to use explicit
                    test.

                    Having said that, it would sure be nice to be able to write
                    >
                    if myList is not empty:
                    >
                    instead of
                    >
                    if len(myList) != 0:
                    I can agree with this.


                    Carl Banks

                    Comment

                    • Russ P.

                      Re: Boolean tests [was Re: Attack a sacred Python Cow]

                      On Jul 29, 10:33 pm, Carl Banks <pavlovevide... @gmail.comwrote :
                      On Jul 30, 1:15 am, "Russ P." <Russ.Paie...@g mail.comwrote:
                      Having said that, it would sure be nice to be able to write
                      >
                      if myList is not empty:
                      >
                      instead of
                      >
                      if len(myList) != 0:
                      >
                      I can agree with this.
                      But I guess that could only work if there were only one empty list
                      that represents all empty lists (as there is only one actual "None").
                      I don't know if that makes sense or not.

                      Comment

                      • Erik Max Francis

                        Re: Boolean tests [was Re: Attack a sacred Python Cow]

                        Carl Banks wrote:
                        Bull. This is a request, that, if satisfied, would prove that "if x"
                        is more polymorphic than a simple explicit test. I posed the question
                        precisely to see if anyone could come up with a use case that shows
                        this benefit of "if x".
                        Except you're the only one who's not convinced of it, and it's your
                        test, and your rules. So who cares?
                        >"if x" _is_ a completely simple
                        >test. Simpler, in fact, than the ones you were advocating.
                        >
                        It's not explicit.
                        It's not explicit enough for you, yes, that much is obvious. Contests
                        that rely on mind-reading aren't too much fun for anyone involved.
                        I've explained why I doubt that it helps polymorphism that much: you
                        almost never see code for which an integer and list both work, so
                        having the ability to spell a test the same way for both types isn't
                        useful. If you claim that "if x" does help polymorphism, please tell
                        me what's wrong with the above analysis.
                        It helps polymorphism for types other that (say) numerics and sequences.
                        There are plenty of container objects for which an "is this
                        non-empty?" test is far simpler a "how many objects are in this
                        container?" test, and several examples have already been given -- as in,
                        O(1) vs. O(n) complexity or worse. You've seem to have even
                        acknowledged this, but are still insisting on continuing the challenge.
                        You're drawing an artificial line in the sand to compare length
                        computation to a more specialized non-emptiness test. (And, as I've
                        pointed out, what happens if you're dealing with a sequence type that
                        _doesn't_ have a length? Then certainly `len(x) != 0` is nonsensical.)

                        Perhaps in the particular use case you're thinking of (numeric types vs.
                        container types), there aren't any good examples. But who cares?
                        Polymorphism applies in more than just this one special case. You're
                        setting up a challenge that isn't very interesting, and which is rigged
                        so that no one can win because you're the one who. So, what's the point?

                        --
                        Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                        San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
                        Can I be your friend / 'Till the end
                        -- India Arie

                        Comment

                        • Erik Max Francis

                          Re: Boolean tests [was Re: Attack a sacred Python Cow]

                          Russ P. wrote:
                          All this discussion about "if x" has me wondering. I use it all the
                          time because a fully explicit test just seems redundant. But maybe it
                          does have some value in terms of readability and type checking. After
                          all, it is possible to forget whether something is a number or a list.
                          >
                          Having said that, it would sure be nice to be able to write
                          >
                          if myList is not empty:
                          I sure hope that's a joke. `x is not y` means something quite different.

                          --
                          Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                          San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
                          The doors of Heaven and Hell are adjacent and identical.
                          -- Nikos Kazantzakis

                          Comment

                          • Erik Max Francis

                            Re: Boolean tests [was Re: Attack a sacred Python Cow]

                            Carl Banks wrote:
                            On Jul 30, 1:15 am, "Russ P." <Russ.Paie...@g mail.comwrote:
                            >All this discussion about "if x" has me wondering. I use it all the
                            >time because a fully explicit test just seems redundant. But maybe it
                            >does have some value in terms of readability and type checking. After
                            >all, it is possible to forget whether something is a number or a list.
                            >
                            IMO, the only time I think "if x" is really dangerous is if you are
                            using "if x" instead of "if x is None" to distinguish between None and
                            a type that can have false values.
                            Well, that would be an exceptionally bad way to test for None-ness,
                            since None is false. The test would never succeed.
                            >Having said that, it would sure be nice to be able to write
                            >>
                            >if myList is not empty:
                            >>
                            >instead of
                            >>
                            >if len(myList) != 0:
                            >
                            I can agree with this.
                            I'm getting this sneaking suspicion that you guys are all putting us on.

                            --
                            Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                            San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
                            The doors of Heaven and Hell are adjacent and identical.
                            -- Nikos Kazantzakis

                            Comment

                            • Erik Max Francis

                              Re: Boolean tests [was Re: Attack a sacred Python Cow]

                              Russ P. wrote:
                              On Jul 29, 10:33 pm, Carl Banks <pavlovevide... @gmail.comwrote :
                              >On Jul 30, 1:15 am, "Russ P." <Russ.Paie...@g mail.comwrote:
                              >
                              >>Having said that, it would sure be nice to be able to write
                              >>if myList is not empty:
                              >>instead of
                              >>if len(myList) != 0:
                              >I can agree with this.
                              >
                              But I guess that could only work if there were only one empty list
                              that represents all empty lists (as there is only one actual "None").
                              I don't know if that makes sense or not.
                              It really doesn't, since it presumably wouldn't apply to just list
                              types. There are plenty of other sequence types: such as tuples,
                              strings, or even arbitrary custom types. Emptiness is a test for the
                              value of an object, not a test for whether it is identical to another
                              object, so this is a very misleading of the `is` operator, bordering on
                              abuse.

                              This syntax would make far less sense than the existing Boolean test.

                              --
                              Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                              San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
                              The doors of Heaven and Hell are adjacent and identical.
                              -- Nikos Kazantzakis

                              Comment

                              • Russ P.

                                Re: Boolean tests [was Re: Attack a sacred Python Cow]

                                On Jul 29, 11:09 pm, Erik Max Francis <m...@alcyone.c omwrote:
                                I'm getting this sneaking suspicion that you guys are all putting us on.
                                As I said in an earlier post, I realize that this would only work if
                                there were only one copy of "empty" (as there is only one copy of
                                "None"). I don't know off hand if that is feasible or not.

                                You reply reeks of the kind of pedantic snobbishness that makes me
                                sick.

                                Comment

                                Working...