accumulators

Discussion in 'Python' started by Eugene Van den Bulke, Jun 12, 2004.

  1. Hi,

    I have just finished reading Paul Graham Hackers & Painters book (which
    I recommend even though he seems a bit hard on Python)

    In chapter 13 of his book he wants to demonstrate LISP power VS other
    languages (to be precise he wants to illustrate what he means by
    relative power of programming language).

    "We want to write a function that generates accumulators - a function
    that takes a number n, and returns a function that takes another number
    i and returns n incremented by i (that's incremented by, not plus. An
    accumulator has to accumulate).

    In Common Lisp this would be:
    (defun foo (n)
    (lambda (i) (incf n i)))

    ....

    Python doesn't fully support lexical variables, you have to create a
    data structure to hold the value of n. And although Python does have a
    function data type, there is no literal representation for one (unless
    the body is only a single expression) so you need to create a named
    function to return. This is what you end up with:

    def foo(n):
    s=[n]
    def bar(i):
    s[0]+=i
    return s[0]
    return bar
    "

    It seems to me that this code does the job (but I am not sure I
    understand exactly what an accumulator is):

    def test(n):
    return lambda i: n+i

    Is that an accumulator? If it is, PG must have written this chapter
    working on an older verion of Python ...

    Regards,

    Eugene Van den Bulke
    Eugene Van den Bulke, Jun 12, 2004
    #1
    1. Advertising

  2. Eugene Van den Bulke

    Paul Rubin Guest

    Eugene Van den Bulke <> writes:
    > It seems to me that this code does the job (but I am not sure I
    > understand exactly what an accumulator is):
    >
    > def test(n):
    > return lambda i: n+i
    >
    > Is that an accumulator? If it is, PG must have written this chapter
    > working on an older verion of Python ...


    No. The idea of an accumulator is that whenever you call it, the
    internal state updates. That is, if accum(n) creates an accumulator,
    you should be able to say:

    a = accum(3) # create accumulator holding 3
    print accum(2) # prints "5"
    print accum(3) # prints "8"
    print accum(1) # prints "9"

    etc. The Pythonic way to do it is with a class instance:

    class accum:
    def __init__(self, n):
    self.s = n
    def __call__(self, i):
    self.s += i
    return self.s

    a = accum(3)
    (etc.)

    however, for programmers comfortable with the Lisp idioms of using
    internal lambdas, the class/object approach is cumbersome.
    Paul Rubin, Jun 12, 2004
    #2
    1. Advertising

  3. Eugene Van den Bulke

    Peter Otten Guest

    Paul Rubin wrote:

    > a = accum(3) # create accumulator holding 3
    > print accum(2) # prints "5"
    > print accum(3) # prints "8"
    > print accum(1) # prints "9"


    Should be

    a = accum(3) # create accumulator holding 3
    print a(2) # prints "5"
    print a(3) # prints "8"
    print a(1) # prints "9"

    Peter
    Peter Otten, Jun 12, 2004
    #3
  4. Eugene Van den Bulke

    Paul Rubin Guest

    Peter Otten <> writes:
    > Should be
    >
    > a = accum(3) # create accumulator holding 3
    > print a(2) # prints "5"
    > print a(3) # prints "8"
    > print a(1) # prints "9"


    Oops, yes.
    Paul Rubin, Jun 12, 2004
    #4
  5. Paul Rubin wrote:
    > Peter Otten <> writes:
    >
    >>Should be
    >>
    >> a = accum(3) # create accumulator holding 3
    >> print a(2) # prints "5"
    >> print a(3) # prints "8"
    >> print a(1) # prints "9"

    >
    >
    > Oops, yes.


    thank you !!!
    Eugene Van den Bulke, Jun 12, 2004
    #5
  6. Paul Rubin wrote:
    > class accum:
    > def __init__(self, n):
    > self.s = n
    > def __call__(self, i):
    > self.s += i
    > return self.s


    Just for fun, a full-blown class with documentation and the like:

    class Accumulator(object):
    """This class implements a simple accumulator. Instate it with a
    starting value, or it will default to 0. It can be called with
    another value, which will be accumulated. The current value will
    also be returned.

    Example:

    >>> a = Accumulator(1)
    >>> a(2)

    3
    >>> a(1)

    4
    >>> a(3)

    7
    """

    __slots__ = '_value'

    def __init__(self, value=0):
    self._value = value

    def __call__(self, value):
    self._value += value
    return self._value

    def __str__(self):
    return str(self._value)

    def __repr__(self):
    return "<Accumulator object with value %s>" % self._value
    Leif K-Brooks, Jun 13, 2004
    #6
  7. Leif K-Brooks <> wrote in message news:<j3Nyc.3335$>...
    > Just for fun, a full-blown class with documentation and the like:
    >
    > class Accumulator(object):
    > """This class implements a simple accumulator. Instate it with a
    > starting value, or it will default to 0. It can be called with
    > another value, which will be accumulated. The current value will
    > also be returned.
    >
    > Example:
    >
    > >>> a = Accumulator(1)
    > >>> a(2)

    > 3
    > >>> a(1)

    > 4
    > >>> a(3)

    > 7
    > """
    >
    > __slots__ = '_value'
    >
    > def __init__(self, value=0):
    > self._value = value
    >
    > def __call__(self, value):
    > self._value += value
    > return self._value
    >
    > def __str__(self):
    > return str(self._value)
    >
    > def __repr__(self):
    > return "<Accumulator object with value %s>" % self._value


    I just don't see the need to use __slots__ here. The first rule about __slots__
    is: don't use them! OTOH the second rule (for expert only) is: don't use them!!

    That's true for any optimization, isnt'it? ;)

    Michele Simionato
    Michele Simionato, Jun 13, 2004
    #7
  8. Paul Rubin wrote:

    > ... The Pythonic way to do it is with a class instance:
    >
    > class accum:
    > def __init__(self, n):
    > self.s = n
    > def __call__(self, i):
    > self.s += i
    > return self.s
    >
    > a = accum(3)
    > (etc.)
    >
    > however, for programmers comfortable with the Lisp idioms of using
    > internal lambdas, the class/object approach is cumbersome.


    The way I'd do it is:

    class accum:
    def __init__(self, start):
    self.runningtotal = start

    def increment(self, value):
    self.runningtotal += value
    return self.runningtotal

    a = accum(3).increment
    Then you can use:
    a(3) ...

    That is, avoid magic names unless needed, and make the names obvious.

    --
    -Scott David Daniels
    Scott David Daniels, Jun 25, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ballpointpenthief

    Maps, filters and accumulators

    ballpointpenthief, Sep 1, 2006, in forum: C Programming
    Replies:
    10
    Views:
    507
    Dave Thompson
    Sep 21, 2006
Loading...

Share This Page