mutable default parameter problem [Prothon]

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Pierre-Frédéric Caillaud

    #31
    Re: mutable default parameter problem [Prothon]


    Nice !
    I wish Python had this, too.

    Also, re-evaluating each time will allow one to use a global variable
    whose value could change as a default parameter. Which looke suspicious.
    Or something like that, which is GOOD :

    class youpi( object ):
    def mymethod( self, a=self.a, b=self.b ):
    ...

    [color=blue]
    > Pierre-Frédéric Caillaud wrote:
    >[color=green][color=darkred]
    >>> 2) Evaluate the default expression once at each call time when the
    >>> default
    >>> value is needed. The default expression would be evaluated in the
    >>> context
    >>> of the function definition (like a closure).[/color]
    >>
    >>
    >> I like Choice 2 because I've always wanted to do the following :
    >>
    >> def func( x, y=2*x ):[/color]
    >
    > It looks like you will get your wish. The voting has been pretty much
    > unanimous for option 2.
    >
    >[/color]



    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/

    Comment

    • Hung Jung Lu

      #32
      Re: mutable default parameter problem [Prothon]

      Rob Williscroft <rtw@freenet.co .uk> wrote:[color=blue]
      >
      > But python has static variables.
      >
      > def another( x ):
      > y = getattr( another, 'static', 10 )
      > another.static = x
      > return y
      >
      > print another(1), another(2), another(4)[/color]

      What about the following case:

      def f():
      f.static = getattr(f, 'static', 0)
      f.static += 1
      return f.static

      print f(), f(), f() # prints 1 2 3

      As opposed to C++, you now have a line of code that is always executed
      in subsequent calls, for no good reason. This is worse than:

      def f(static=[0]):
      static[0] += 1
      return static[0]

      in the sense that you have a wasteful call ("getattr") that doesn't do
      anything productive in subsequent calls. (You could change that to
      f.static = getattr(f, 'static', 0) + 1, but the "getattr" is surely
      inefficient compared to f.static += 1, and internally likely incurs
      some conditional statement at some level.)

      Maybe one can do instead:

      def f():
      global f
      def f():
      f.static += 1
      return f.static
      f.static = 0 # initialization
      return f()

      print f(), f(), f() # prints 1 2 3

      The advantage is there is no more wasteful statements in subsequent
      calls. No "if" conditional statement. The above is of course a toy
      example to illustrate the case of a function that needs to perform
      something special the first time it is called. (I am well aware of the
      outside assignment like:

      def f():
      f.static += 1
      return f.static
      f.static = 0

      mentioned in this thread, but I am talking about something more
      general. Notice that in the latter case, f.static=0 is done before f()
      is called, which may not be what one wants. E.g.: if f() is never
      called, this assignment is wasteful. Not a problem in this case, for
      if complicated initialization is needed, like requiring a timestamp,
      it may not be a good idea.)

      In code refactoring, the equivalent is to replace conditional
      statements by polymorphism. In terms of codeblocks, what I mean is
      dynamic hook-on and hook-off of codeblocks. If the underlying language
      is powerful enough, one should be able to achieve runtime
      restructuring of code, without performance impact for subsequent
      calls.

      regards,

      Hung Jung

      Comment

      • Mark Hahn

        #33
        Re: mutable default parameter problem [Prothon]

        Hung Jung Lu wrote:
        [color=blue]
        > In code refactoring, the equivalent is to replace conditional
        > statements by polymorphism. In terms of codeblocks, what I mean is
        > dynamic hook-on and hook-off of codeblocks. If the underlying language
        > is powerful enough, one should be able to achieve runtime
        > restructuring of code, without performance impact for subsequent
        > calls.[/color]

        What about this Prothon code:

        def f():
        if 'static' not in f.attrs_:
        f.static = 0
        f.static += 1

        tmp = f.static
        def outer.f():
        f.static += 1
        return f.static
        f.static = tmp

        return f.static

        print f() # 1
        print f() # 2
        print f() # 3

        I'm sure Python can do this better so please don't barrage me with replies
        saying so. I'm not going to brag this time :-)


        Comment

        • Peter Hansen

          #34
          Re: mutable default parameter problem [Prothon]

          Mark Hahn wrote:
          [color=blue]
          > I also said I was
          > sorry in my very first posting. If you want me to repeat this a third time
          > I will.[/color]

          It's likely that Christos' Usenet link (if that's how he gets
          this group) is much slower than yours or mine... he may not
          have received (or at least read) either of the other replies
          by the time he sent his own...

          Or, he might just want you to repeat it a third time. ;-)

          -Peter

          Comment

          • Rob Williscroft

            #35
            Re: mutable default parameter problem [Prothon]

            Hung Jung Lu wrote in news:8ef9bea6.0 406180809.10053 ba6@posting.goo gle.com
            in comp.lang.pytho n:
            [color=blue]
            > Rob Williscroft <rtw@freenet.co .uk> wrote:[color=green]
            >>
            >> But python has static variables.
            >>
            >> def another( x ):
            >> y = getattr( another, 'static', 10 )
            >> another.static = x
            >> return y
            >>
            >> print another(1), another(2), another(4)[/color]
            >
            > What about the following case:
            >
            > def f():
            > f.static = getattr(f, 'static', 0)
            > f.static += 1
            > return f.static
            >
            > print f(), f(), f() # prints 1 2 3[/color]

            Yep this would be the way I would instinctivly write it. However
            Andrea suggested:

            def f():
            if not hasattr( f, 'static', 0 ):
            f.static = 0
            f.static += 1
            return f.static

            Which my primitive timing tests show to be faster.
            [color=blue]
            >
            > As opposed to C++, you now have a line of code that is always executed
            > in subsequent calls, for no good reason. This is worse than:[/color]

            Well C++ has `if ( __compiler_gene rated_bool__ )` that will always
            be executed ( except in the case of POD's (char, int, double etc) ).
            [color=blue]
            >
            > def f(static=[0]):
            > static[0] += 1
            > return static[0][/color]


            I don't know but surely the interpreter is doing some kind of
            extra if/attribute lookup in there, its just faster than the
            other versions.

            I've timed both, and this was by far the fastest. I don't think
            the problems is the `if` though. I don't know but I suspect this
            version finds the local/paramiter 'static' with __slots__ like
            performance, all other version's suffer from attribute lookup
            problems.
            [color=blue]
            >
            > in the sense that you have a wasteful call ("getattr") that doesn't do
            > anything productive in subsequent calls. (You could change that to
            > f.static = getattr(f, 'static', 0) + 1, but the "getattr" is surely
            > inefficient compared to f.static += 1, and internally likely incurs
            > some conditional statement at some level.)
            >
            > Maybe one can do instead:
            >
            > def f():
            > global f
            > def f():
            > f.static += 1
            > return f.static
            > f.static = 0 # initialization
            > return f()
            >
            > print f(), f(), f() # prints 1 2 3
            >
            > The advantage is there is no more wasteful statements in subsequent
            > calls. No "if" conditional statement.[/color]

            Intresting, but it looses (in my timing tests) to the f(static=[0])
            version, static[0] must be faster than f.static I guess.
            [color=blue]
            > The above is of course a toy
            > example to illustrate the case of a function that needs to perform
            > something special the first time it is called. (I am well aware of the
            > outside assignment like:
            >
            > def f():
            > f.static += 1
            > return f.static
            > f.static = 0
            >
            > mentioned in this thread, but I am talking about something more
            > general. Notice that in the latter case, f.static=0 is done before f()
            > is called, which may not be what one wants. E.g.: if f() is never
            > called, this assignment is wasteful. Not a problem in this case, for
            > if complicated initialization is needed, like requiring a timestamp,
            > it may not be a good idea.)[/color]

            Indeed, the fast version is:

            _f_static = 0
            def f():
            global _f_static
            _f_static += 1
            return _f_static

            This is directly equivalent to
            <c++>
            static int f_static = 0;
            int f() { return ++f_static; }
            </c++>

            C++ name hiding is with the static keyword, python name hiding
            is with a leading underscore.
            [color=blue]
            >
            > In code refactoring, the equivalent is to replace conditional
            > statements by polymorphism. In terms of codeblocks, what I mean is
            > dynamic hook-on and hook-off of codeblocks. If the underlying language
            > is powerful enough, one should be able to achieve runtime
            > restructuring of code, without performance impact for subsequent
            > calls.
            >[/color]

            Nice.

            <c++>
            static int f_static;
            static int f_init();
            static int f_run();
            int (*f)() = f_init();

            static int f_init()
            {
            f_static = /* dynamic value */ 0;
            f = f_run;
            return f();
            }
            static int f_run()
            {
            return ++f_static;
            }
            </c++>

            In C++ the (performance) cost is visible and only f() and its callers
            pay for it, in Python the the (performance) cost is invisible and
            everybody pays for it.

            In C++ I write:

            int f()
            {
            static int var = 0;
            return ++var;
            }

            And I let the compiler worry about the best way to implement it,
            in Python I write:

            class f( object ):
            def __init__( self ):
            self.var = 0;
            def run( self ):
            self.var += 1
            return self.var

            Though in a simple case (as all the examples have been) I
            might write:

            def f():
            if not hasattr( f, 'static' ):
            f.static = 0
            f.static += 1
            return f.static

            Clarity (my clairty of purpose, as a programmer) wins in
            both languages.

            I won't be writing:

            def f(static=[0]):
            #etc

            It simply isn't clear.

            Rob.
            --

            Comment

            • Christos TZOTZIOY Georgiou

              #36
              Re: mutable default parameter problem [Prothon]

              On Fri, 18 Jun 2004 20:38:51 -0400, rumours say that Peter Hansen
              <peter@engcorp. com> might have written:
              [color=blue][color=green]
              >> I also said I was
              >> sorry in my very first posting. If you want me to repeat this a third time
              >> I will.[/color]
              >
              >It's likely that Christos' Usenet link (if that's how he gets
              >this group) is much slower than yours or mine... he may not
              >have received (or at least read) either of the other replies
              >by the time he sent his own...
              >
              >Or, he might just want you to repeat it a third time. ;-)[/color]

              I am actually reading through Usenet... the newsserver link is fast, but
              the arrival order of posts is not guaranteed, so I don't read messages
              in the same order as people using the mail list. Often I post a reply
              to a single message, only to find in the next synchronisation that
              others did reply even earlier than me saying more or less the same
              things. Other times I don't bother, saying "somebody else will reply to
              this trivial question", and next day I find out that everybody else
              thought the same as I did. That's Usenet (sigh).
              --
              TZOTZIOY, I speak England very best,
              "Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek

              Comment

              • Mark Hahn

                #37
                Re: mutable default parameter problem [Prothon]


                "Dave Brueck" <dave@pythonapo crypha.com> wrote
                [color=blue][color=green]
                > > FYI: It's not that the exclamation mark causes append to return the
                > > sequence. The exclamation mark is always there and the sequence is[/color][/color]
                always[color=blue][color=green]
                > > returned. The exclamation mark is the universal symbol for in-place
                > > modification. This is straight from Ruby and solves the problem that[/color]
                > caused[color=green]
                > > Guido to not allow sequences to be returned. And, yes, I do think[/color][/color]
                that's[color=blue][color=green]
                > > worth bragging about ;-)[/color]
                >
                > Wait, so is the exclamation point required or not? IOW, say you have a[/color]
                class[color=blue]
                > like this:
                >
                > class List(list):
                > def append(self, what):
                > list.append(sel f, what)
                > return self
                >
                > a = List()
                > b = a.append(5)
                >
                > So in the call to append, is it a.append!(5) or just a.append(5) ? If it's
                > the former, then does the compiler detect that it's required because the
                > function returns 'self' or is the determining factor something else?
                >
                > Or, does the append method not really return anything, and the language
                > takes care of substituting in the object? (in which case, does that mean[/color]
                you[color=blue]
                > can override the return value by adding '!' - such that z=foo.bar!()[/color]
                ignores[color=blue]
                > the return value of bar and z references foo?)[/color]

                As I said above: It's not that the exclamation mark that causes append to
                return the sequence. The exclamation mark is always there and the sequence
                is always returned. In Prothon (and Ruby and other languages before) the
                exclamation mark is just part of the method name and is there to warn you
                that in-place modification is happening.
                [color=blue]
                > Personally, I don't like the modify-in-place-and-return-the-object
                > 'feature' - it's not needed _that_ often, but more importantly, it makes[/color]
                the[color=blue]
                > code harder to read (to me at least).[/color]

                If you use the Prothon append!() exactly as you use the Python append() you
                will get the exact same results. This is just an extra feature for those
                that want it.

                Guido avoided returning values from in-place modification functions because
                of the confusion as to whether in-place mods were happening or not. We have
                solved that confusion with the exclamation mark. Our code is very readable
                because of this.




                Comment

                • Mark Hahn

                  #38
                  Re: mutable default parameter problem [Prothon]

                  Christos TZOTZIOY Georgiou wrote:
                  [color=blue][color=green]
                  >> Or, he might just want you to repeat it a third time. ;-)[/color]
                  >
                  > I am actually reading through Usenet... the newsserver link is fast,
                  > but the arrival order of posts is not guaranteed, so I don't read
                  > messages in the same order as people using the mail list. Often I
                  > post a reply to a single message, only to find in the next
                  > synchronisation that others did reply even earlier than me saying
                  > more or less the same things. Other times I don't bother, saying
                  > "somebody else will reply to this trivial question", and next day I
                  > find out that everybody else thought the same as I did. That's
                  > Usenet (sigh).[/color]

                  I'm sorry if I was rude. It is always when I make a stupid remark on a
                  public forum that I am asked to repeat it :-) No one ever asks me to repeat
                  a witty gem. (Of course maybe that never occurs).


                  Comment

                  • Christos TZOTZIOY Georgiou

                    #39
                    Re: mutable default parameter problem [Prothon]

                    On Thu, 24 Jun 2004 17:06:33 -0700, rumours say that "Mark Hahn"
                    <mark@prothon.o rg> might have written:
                    [color=blue]
                    >No one ever asks me to repeat
                    >a witty gem.[/color]

                    You can say that again :)
                    --
                    TZOTZIOY, I speak England very best,
                    "Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek

                    Comment

                    • Dave Brueck

                      #40
                      Re: mutable default parameter problem [Prothon]

                      Mark wrote:[color=blue][color=green]
                      > > Wait, so is the exclamation point required or not? IOW, say you have a[/color]
                      > class[color=green]
                      > > like this:
                      > >
                      > > class List(list):
                      > > def append(self, what):
                      > > list.append(sel f, what)
                      > > return self
                      > >
                      > > a = List()
                      > > b = a.append(5)
                      > >
                      > > So in the call to append, is it a.append!(5) or just a.append(5) ? If[/color][/color]
                      it's[color=blue][color=green]
                      > > the former, then does the compiler detect that it's required because the
                      > > function returns 'self' or is the determining factor something else?
                      > >
                      > > Or, does the append method not really return anything, and the language
                      > > takes care of substituting in the object? (in which case, does that mean[/color]
                      > you[color=green]
                      > > can override the return value by adding '!' - such that z=foo.bar!()[/color]
                      > ignores[color=green]
                      > > the return value of bar and z references foo?)[/color]
                      >
                      > As I said above: It's not that the exclamation mark that causes append to
                      > return the sequence. The exclamation mark is always there and the[/color]
                      sequence[color=blue]
                      > is always returned. In Prothon (and Ruby and other languages before) the
                      > exclamation mark is just part of the method name and is there to warn you
                      > that in-place modification is happening.[/color]

                      Ahh...so the method name is just _spelled_ with an exclamation point? IOW,
                      the ! is a token you can use at the end of an identifier, but it is not
                      actually used by the language itself - it's some sort of pseudo-syntax? I
                      think I understand now. But is it truly part of the name in that you are
                      required to include the ! when calling the method? (I'm still thinking of
                      the confusion I'd experience with something like w = x.y.z!() )

                      So if I want a reference to one of those methods I could end up doing

                      ref = obj.method! or ref! = obj.method!

                      and the program runs the same either way, it's just that in one case the
                      code is misleading?

                      If it's up to the programmer to remember to add it (meaning that it doesn't
                      cause an error to forget to use it), and if is really just part of the name,
                      then it's just a naming convention, right? Wouldn't you get the same result
                      by establishing the convention that e.g. method names ending in a single
                      underscore signify in-place modification (foo.append_() ) ? Seems like a
                      waste to reserve a symbol for something so rarely needed.
                      [color=blue][color=green]
                      > > Personally, I don't like the modify-in-place-and-return-the-object
                      > > 'feature' - it's not needed _that_ often, but more importantly, it makes[/color]
                      > the[color=green]
                      > > code harder to read (to me at least).[/color]
                      >
                      > If you use the Prothon append!() exactly as you use the Python append()[/color]
                      you[color=blue]
                      > will get the exact same results. This is just an extra feature for those
                      > that want it.
                      >
                      > Guido avoided returning values from in-place modification functions[/color]
                      because[color=blue]
                      > of the confusion as to whether in-place mods were happening or not. We[/color]
                      have[color=blue]
                      > solved that confusion with the exclamation mark. Our code is very[/color]
                      readable[color=blue]
                      > because of this.[/color]

                      Clearly, readability is in the eye of the beholder. :)

                      -Dave


                      Comment

                      • Mark Hahn

                        #41
                        Re: mutable default parameter problem [Prothon]

                        Dave Brueck wrote:
                        [color=blue]
                        > Ahh...so the method name is just _spelled_ with an exclamation point?[/color]

                        Yes, a Prothon identifier is the same as a Python identifier except that it
                        can end with an exclamation mark ( ! )or a question mark ( ? ). These marks
                        can only appear at the end and there can only be one. It is up to the
                        programmer to make sure he/she uses them properly.

                        Exclamation marks are to be used in identifiers if and only if it is a
                        method that modifies the target in-place.

                        Question marks are to be used on methods if and only if they return True or
                        False and nothing else.
                        [color=blue]
                        > IOW, the ! is a token you can use at the end of an identifier, but it
                        > is not actually used by the language itself -[/color]

                        No, the marks are significant to the language just as any other part of the
                        identifier is.
                        [color=blue]
                        > Seems like a waste to reserve a
                        > symbol for something so rarely needed.[/color]

                        I disagree. In-place modification is significant and happens often.
                        Ignoring this is dangerous.
                        [color=blue][color=green][color=darkred]
                        >>> Personally, I don't like the modify-in-place-and-return-the-object
                        >>> 'feature' - it's not needed _that_ often, but more importantly, it
                        >>> makes the code harder to read (to me at least).[/color]
                        >>
                        >> If you use the Prothon append!() exactly as you use the Python
                        >> append() you will get the exact same results. This is just an extra
                        >> feature for those that want it.
                        >>
                        >> Guido avoided returning values from in-place modification functions
                        >> because of the confusion as to whether in-place mods were happening
                        >> or not. We have solved that confusion with the exclamation mark.
                        >> Our code is very readable because of this.[/color]
                        >
                        > Clearly, readability is in the eye of the beholder. :)[/color]

                        How can you argue that the exclamation mark indicating in-place-modification
                        does not make it more readable? Several other languages feel so also. We
                        didn't just make this up.


                        Comment

                        • Christopher T King

                          #42
                          Re: mutable default parameter problem [Prothon]

                          Dave Brueck wrote:
                          [color=blue]
                          > Seems like a waste to reserve a
                          > symbol for something so rarely needed.[/color]

                          Lisp and Scheme do the same thing:

                          (set! a 5) <- sets a variable (i.e. changes its value)
                          (eq? a 6) <- tests equality (returns true or false)

                          It's defined precisely because it's not needed often (at least in the !
                          case): the functions that modify their arguments are few and far between,
                          so it is best to warn the programmer of this behaviour.

                          Though ? doesn't have such a pressing case as !, it does make code easier
                          to read (distinguishing functions that do something from those that make
                          simple queries).

                          Comment

                          • Dave Brueck

                            #43
                            Re: mutable default parameter problem [Prothon]

                            Christopher wrote:[color=blue][color=green]
                            > > Seems like a waste to reserve a
                            > > symbol for something so rarely needed.[/color]
                            >
                            > Lisp and Scheme do the same thing:
                            >
                            > (set! a 5) <- sets a variable (i.e. changes its value)
                            > (eq? a 6) <- tests equality (returns true or false)
                            >
                            > It's defined precisely because it's not needed often (at least in the !
                            > case): the functions that modify their arguments are few and far between,
                            > so it is best to warn the programmer of this behaviour.[/color]

                            An apples-to-oranges comparison, IMO - it makes sense to delimit a side
                            effect in a functional language.

                            -Dave


                            Comment

                            • Pierre-Frédéric Caillaud

                              #44
                              Re: mutable default parameter problem [Prothon]


                              Even though ? and ! feel awkward, I still think they make it more
                              readable.
                              Does the language enforce the bool return type on the ? variant ?

                              Comment

                              • Dave Brueck

                                #45
                                Re: mutable default parameter problem [Prothon]

                                Mark wrote:[color=blue][color=green]
                                > > Ahh...so the method name is just _spelled_ with an exclamation point?[/color]
                                >
                                > Yes, a Prothon identifier is the same as a Python identifier except that[/color]
                                it[color=blue]
                                > can end with an exclamation mark ( ! )or a question mark ( ? ). These[/color]
                                marks[color=blue]
                                > can only appear at the end and there can only be one. It is up to the
                                > programmer to make sure he/she uses them properly.
                                >
                                > Exclamation marks are to be used in identifiers if and only if it is a
                                > method that modifies the target in-place.
                                >
                                > Question marks are to be used on methods if and only if they return True[/color]
                                or[color=blue]
                                > False and nothing else.
                                >[color=green]
                                > > IOW, the ! is a token you can use at the end of an identifier, but it
                                > > is not actually used by the language itself -[/color]
                                >
                                > No, the marks are significant to the language just as any other part of[/color]
                                the[color=blue]
                                > identifier is.[/color]

                                You cut out my example that elaborated on the questions I was asking:

                                1) It's just part of the name. So from the language's perspective, whether
                                you call it appendINPLACE or append! makes no difference?

                                2) (continuing on #1) that being the case, it's really just a naming
                                convention, correct? (because the language itself doesn't do anything with
                                that information - additional checking to enforce that convention, different
                                functionality, etc)
                                [color=blue]
                                >From what I gather that's a "yes" to both questions.[/color]
                                [color=blue][color=green]
                                > > Seems like a waste to reserve a
                                > > symbol for something so rarely needed.[/color]
                                >
                                > I disagree. In-place modification is significant and happens often.
                                > Ignoring this is dangerous.[/color]

                                Well, now we're down to disagreeing how often it occurs. I just haven't seen
                                very many cases in practice where (1) I want to both do something to an
                                object AND have it return itself in a single step and (2) doing so can be
                                done in a clear way, and (3) I want to do it for a good reason rather than
                                just wanting to save a line of code. In the few cases I've seen so far, the
                                rationale has apparently been to make the code shorter, not necessarily
                                better.
                                [color=blue][color=green][color=darkred]
                                > >> Guido avoided returning values from in-place modification functions
                                > >> because of the confusion as to whether in-place mods were happening
                                > >> or not. We have solved that confusion with the exclamation mark.
                                > >> Our code is very readable because of this.[/color]
                                > >
                                > > Clearly, readability is in the eye of the beholder. :)[/color]
                                >
                                > How can you argue that the exclamation mark indicating[/color]
                                in-place-modification[color=blue]
                                > does not make it more readable?[/color]

                                (1) Because in practice I haven't seen the need for it much, so in my mind
                                it wouldn't be used that much (making it less familiar & therefore more work
                                to understand the code) and/or it encourages cramming more onto a line just
                                because you can.

                                The "print list.append!(5) " is a fine example of this IMO - you've combined
                                two *completely unrelated* operations for no good reason. Yes, it's just an
                                example, I know, but it's probably an example of how it'll be commonly
                                (mis)used. For every one "good" use of the ! form you'll probably have a
                                thousand uses where the only benefit was that it saved a line of code. <0.5
                                wink>

                                (2) It's just a naming convention, so you can't rely on it's presence or
                                absence as being accurate (probably not a big deal in practice, but
                                still...)

                                (3) Cases like w = x.y.z!() would confuse me, as would

                                ref! = obj.method!
                                ....
                                x = ref!(5, 6, 7) # what the heck, x == obj?!

                                -Dave


                                Comment

                                Working...