No "side effect" assignment!

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

    No "side effect" assignment!

    Ok,

    I miss the idiom that my other languages use,
    something like:


    while( foo = getmore()){
    process(foo);
    }


    I can't seem to do this in python without gagging:

    foo = getmore()
    while foo:
    process(foo)
    foo = getmore()


    Is that what ppl do? The manual sez that this is
    so that newbs won't do:

    if foo = bar:
    process()

    thinking that they are checking for equality.
    I feel that in a few ways python suffers by catering
    to the uninitiated. Usually however, there are
    great workarounds (or even plain better ways to do the job),
    which I am hopeful will be yielded by the list, as has
    been it's record thus far to do.

    Thanks,

    Tobiah

  • Dave Kuhlman

    #2
    Re: No "side effect" assignment!

    Tobiah wrote:

    [snip][color=blue]
    >
    >
    > I can't seem to do this in python without gagging:
    >
    > foo = getmore()
    > while foo:
    > process(foo)
    > foo = getmore()[/color]

    Then test your gag reflex on the following:

    while 1:
    foo = getmore()
    if not foo:
    break
    process(foo)

    Slips down pretty smoothly with me.

    [snip]

    Dave

    --
    Dave Kuhlman

    dkuhlman@rexx.c om

    Comment

    • Tobiah

      #3
      Re: No "side effect" assignment!

      Ack!!! (slight gag reflex) :)

      That's actually more lines, even if more readable.

      Ok, my perl roots are showing, but I was thinking
      of putting the following function into my standard
      module:

      def eq(thingy):
      global _
      _ = thingy
      return _



      Having done that, I can now say:

      while eq(getmore()):
      process(_)


      It seems to me that adding support for the side effect
      assignment would not break any existing scripts. Gee,
      they did it for += ;)

      Thanks,

      Tobiah
      [color=blue]
      > Then test your gag reflex on the following:
      >
      > while 1:
      > foo = getmore()
      > if not foo:
      > break
      > process(foo)
      >
      > Slips down pretty smoothly with me.
      >
      > [snip]
      >
      > Dave
      >[/color]

      Comment

      • John Roth

        #4
        Re: No "side effect" assignment!


        "Tobiah" <toby@rcsreg.co m> wrote in message
        news:0fbc28ebd2 ba4810db3efef3a 29f990a@news.te ranews.com...[color=blue]
        > Ok,
        >
        > I miss the idiom that my other languages use,
        > something like:
        >
        >
        > while( foo = getmore()){
        > process(foo);
        > }
        >
        >
        > I can't seem to do this in python without gagging:
        >
        > foo = getmore()
        > while foo:
        > process(foo)
        > foo = getmore()
        >
        >
        > Is that what ppl do? The manual sez that this is
        > so that newbs won't do:
        >
        > if foo = bar:
        > process()
        >
        > thinking that they are checking for equality.
        > I feel that in a few ways python suffers by catering
        > to the uninitiated. Usually however, there are
        > great workarounds (or even plain better ways to do the job),
        > which I am hopeful will be yielded by the list, as has
        > been it's record thus far to do.[/color]

        While one of Guido's reasons for not including assignment
        as an expression was to avoid errors (and that's not always
        a novice error,) Python provides similar functionality in the
        'for' statement. In C, C++ and Java, 'for' is basically
        syntactic sugar around a loop, in Python, it actually does
        an assignment of the next element of a sequence.

        Your example could be:

        for foo in getmore:
        process(foo)

        as long as getmore is either a sequence or implements the
        iterator protocol.

        This isn't a total replacement for assignment as an expression,
        but it does cover the overwhelming majority of use cases.

        John Roth

        [color=blue]
        >
        > Thanks,
        >
        > Tobiah
        >[/color]


        Comment

        • Sean Ross

          #5
          Re: No &quot;side effect&quot; assignment!

          "Tobiah" <toby@rcsreg.co m> wrote in message
          news:0fbc28ebd2 ba4810db3efef3a 29f990a@news.te ranews.com...[color=blue]
          > Ok,
          >
          > I miss the idiom that my other languages use,
          > something like:
          >
          >
          > while( foo = getmore()){
          > process(foo);
          > }
          >[/color]
          [snip]

          If you must use assignments in expressions, you might find the following
          recipes useful:





          Comment

          • Andrew Koenig

            #6
            Re: No &quot;side effect&quot; assignment!

            Tobiah> Ack!!! (slight gag reflex) :)
            Tobiah> That's actually more lines, even if more readable.

            Tobiah> Ok, my perl roots are showing, but I was thinking
            Tobiah> of putting the following function into my standard
            Tobiah> module:

            Tobiah> def eq(thingy):
            Tobiah> global _
            Tobiah> _ = thingy
            Tobiah> return _



            Tobiah> Having done that, I can now say:

            Tobiah> while eq(getmore()):
            Tobiah> process(_)

            You're right -- your Perl roots are showing.

            How about this instead:

            def make_generator( func):
            while x = func():
            yield x

            for val in make_generator( getmore):
            process(val)

            --
            Andrew Koenig, ark@acm.org

            Comment

            • Erik Max Francis

              #7
              Re: No &quot;side effect&quot; assignment!

              Andrew Koenig wrote:
              [color=blue]
              > How about this instead:
              >
              > def make_generator( func):
              > while x = func():[/color]
              ^^^^^^^^^^

              Not too likely in Python :-).

              --
              Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
              __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
              / \ Youth is a period of missed opportunities.
              \__/ Cyril Connolly

              Comment

              • Tobiah

                #8
                Re: No &quot;side effect&quot; assignment!

                Erik Max Francis wrote:[color=blue]
                > Andrew Koenig wrote:
                >
                >[color=green]
                >>How about this instead:
                >>
                >> def make_generator( func):
                >> while x = func():[/color]
                >
                > ^^^^^^^^^^
                >
                > Not too likely in Python :-).
                >[/color]

                Heh! My point exactly :)

                Comment

                • Asun Friere

                  #9
                  Re: No &quot;side effect&quot; assignment!

                  Dave Kuhlman <dkuhlman@rexx. com> wrote in message news:<bk2okk$nr hg9$1@ID-139865.news.uni-berlin.de>...[color=blue]
                  > Tobiah wrote:
                  >
                  > [snip][color=green]
                  > >
                  > >
                  > > I can't seem to do this in python without gagging:
                  > >
                  > > foo = getmore()
                  > > while foo:
                  > > process(foo)
                  > > foo = getmore()[/color]
                  >
                  > Then test your gag reflex on the following:
                  >
                  > while 1:
                  > foo = getmore()
                  > if not foo:
                  > break
                  > process(foo)
                  >
                  > Slips down pretty smoothly with me.
                  >
                  > [snip]
                  >
                  > Dave[/color]

                  I am alone in feeling some slight unease at the sight of "while 1: ...
                  break"? I know this is considered somewhat pythonic, but apart from
                  the fact that there is only a single assignment statement is there
                  really any advantage to be gained by doing it this way? It seems to
                  be trading one aesthetic disadvantage for another, and imho, a
                  marginally less legible one.

                  In terms of pandering to newbies, I think the requirement that loop
                  conditions be expressions is much more squarely aimed at experienced
                  programmers, who would otherwise be tempted to write unintelligible
                  code by placing too much of the programs logic withing the loop
                  condition.

                  Comment

                  • Duncan Booth

                    #10
                    Re: No &quot;side effect&quot; assignment!

                    Tobiah <toby@rcsreg.co m> wrote in
                    news:0fbc28ebd2 ba4810db3efef3a 29f990a@news.te ranews.com:
                    [color=blue]
                    > I can't seem to do this in python without gagging:
                    >
                    > foo = getmore()
                    > while foo:
                    > process(foo)
                    > foo = getmore()
                    >
                    >
                    > Is that what ppl do?[/color]

                    I don't know about ppl, but Python programmers have a variety of ways of
                    structuring this code. The one that I think is simplest, but is often
                    overlooked is to use the builtin function 'iter'. It won't exactly replace
                    the code you have above, since your loop terminates as soon as getmore()
                    returns anything false (None, 0, False, '' would all terminate it). If
                    however you know the exact value to indicate termination (I'll guess
                    getmore() returns None when its done), you can write your loop:

                    for foo in iter(getmore, None):
                    process(foo)

                    If instead of a simple function call you had a more complex expression (say
                    getmore took a file as an argument), you might consider a lambda:

                    for foo in iter(lambda: getmore(aFile), None):
                    process(foo)


                    --
                    Duncan Booth duncan@rcp.co.u k
                    int month(char *p){return(1248 64/((p[0]+p[1]-p[2]&0x1f)+1)%12 )["\5\x8\3"
                    "\6\7\xb\1\x9\x a\2\0\4"];} // Who said my code was obscure?

                    Comment

                    • Peter Hansen

                      #11
                      Re: No &quot;side effect&quot; assignment!

                      Asun Friere wrote:[color=blue]
                      >
                      > Dave Kuhlman wrote:[color=green]
                      > > while 1:
                      > > foo = getmore()
                      > > if not foo:
                      > > break
                      > > process(foo)[/color]
                      >
                      > I am alone in feeling some slight unease at the sight of "while 1: ...
                      > break"? I know this is considered somewhat pythonic, but apart from
                      > the fact that there is only a single assignment statement is there
                      > really any advantage to be gained by doing it this way? It seems to
                      > be trading one aesthetic disadvantage for another, and imho, a
                      > marginally less legible one.[/color]

                      There is a distinct advantage in the above, over the form with
                      a duplicated line, and it's nothing to do with aesthetics. Sure,
                      they both may be ugly to you (but they feel quite simple and thus
                      elegant to some experienced Python programmers), but the real issue
                      is that the one has the duplicated assignment and is therefore prone
                      to maintenance problems. This fact alone far outweighs any aesthetic
                      consideration, and wholly justifies the above form.

                      If you are really offended, use a wrapper of some kind as others have
                      shown.

                      -Peter

                      Comment

                      • Christopher A. Craig

                        #12
                        Re: No &quot;side effect&quot; assignment!

                        afriere@yahoo.c o.uk (Asun Friere) writes:
                        [color=blue]
                        > I am alone in feeling some slight unease at the sight of "while 1: ...
                        > break"? I know this is considered somewhat pythonic, but apart from
                        > the fact that there is only a single assignment statement is there
                        > really any advantage to be gained by doing it this way? It seems to
                        > be trading one aesthetic disadvantage for another, and imho, a
                        > marginally less legible one.[/color]

                        While I agree with you, I don't think I'd bother with changing thel
                        language now to fix it. If I were writing a new language I'd prefer a
                        loop-and-a-half structure something like this:

                        repeat:
                        stuff
                        while test:
                        stuff

                        I'd really prefer something like the above without the second colon.
                        While it's nice to have the condition dedented for readability, it
                        isn't really starting a new block. At any rate, I don't think adding
                        this to the current language is worth it, so I'll keep using "while 1:
                        break" structures and translating to the above in my head.

                        --
                        Christopher A. Craig <list-python@ccraig.o rg>
                        "So we who are many, are one body in Christ, and individually members
                        one of another." Romans 12:5 (NASB)


                        Comment

                        • John J. Lee

                          #13
                          Re: No &quot;side effect&quot; assignment!

                          Tobiah <toby@rcsreg.co m> writes:
                          [color=blue]
                          > Erik Max Francis wrote:[color=green]
                          > > Andrew Koenig wrote:
                          > >[color=darkred]
                          > >>How about this instead:
                          > >>
                          > >> def make_generator( func):
                          > >> while x = func():[/color]
                          > > ^^^^^^^^^^
                          > > Not too likely in Python :-).
                          > >[/color]
                          >
                          > Heh! My point exactly :)[/color]

                          def f(): return raw_input()

                          for x in iter(f, ""):
                          print x


                          If you want to be more vague about the sentinel (a bad idea, and
                          equivalent to your Perl example), I suppose you could use something
                          obscure like this:

                          class FalsehoodSentin el:
                          def __cmp__(self, other): return int(bool(other) )
                          falsehoodsentin el = FalsehoodSentin el()


                          and then:

                          def f(): return raw_input()

                          for x in iter(f, falsehoodsentin el):
                          print x


                          So that *any* false value from f will end the for loop. Don't do
                          that, though -- explicit is better...

                          Of course, most of the time, having written your program Pythonishly,
                          not Perlishly, you'll have iterators in the first place, and won't
                          need to turn them into an iterator by hand.


                          John

                          Comment

                          • Terry Reedy

                            #14
                            Re: No &quot;side effect&quot; assignment!


                            "John J. Lee" <jjl@pobox.co m> wrote in message
                            news:87smmyndi1 .fsf@pobox.com. ..[color=blue]
                            > def f(): return raw_input()
                            >
                            > for x in iter(f, ""):
                            > print x[/color]

                            Nice -- I keep forgetting about iter() -- except that the wrapper
                            adds nothing that I can see.
                            [color=blue][color=green][color=darkred]
                            >>> for l in iter(raw_input, ''): print '*', l, '*'[/color][/color][/color]
                            ....
                            aksjf
                            * aksjf *
                            jslfkj
                            * jslfkj *
                            [color=blue][color=green][color=darkred]
                            >>>[/color][/color][/color]

                            Terry J. Reedy



                            Comment

                            • Martin Maney

                              #15
                              Re: No &quot;side effect&quot; assignment!

                              Asun Friere <afriere@yahoo. co.uk> wrote:[color=blue]
                              > In terms of pandering to newbies, I think the requirement that loop
                              > conditions be expressions is much more squarely aimed at experienced
                              > programmers, who would otherwise be tempted to write unintelligible
                              > code by placing too much of the programs logic withing the loop
                              > condition.[/color]

                              Uhm, no. *Experienced* programmers know better than to take usch
                              things to excess, unless the code is being written for a obfuscated
                              code contest. As is so often the case, it's those difficult
                              in-betweeners, no longer innocent by virtue of ignorance, not yet
                              grown wise enough to eschew the merely clever, who bollix it all up for
                              the rest of us.

                              --
                              Threaten not the comic with your lawyers' bluster,
                              all toothless to supress parody and satire;
                              for you will not amuse him, but you may inspire him.
                              (me, inspired by http://www.netfunny.com/rhf/jokes/01/Apr/mcrhf.html)

                              Comment

                              Working...