Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Aug 13th, 2006, 11:20 AM   #1
Dietrich
Professional Programmer
 
Dietrich's Avatar
 
Join Date: Feb 2005
Posts: 434
Rep Power: 4 Dietrich is on a distinguished road
Mystery (to me) Function

I picked this function up on the net. It is described as an accumulator generator, but I cannot figure out what it can be used for. Any help?
def make_acc(start=0):
    """accumulator generator """
    curr = [start]
    def acc(inc):
        curr[0] += inc
        return curr[0]
    return acc
__________________
I looked it up on the Intergnats!
Dietrich is offline   Reply With Quote
Old Aug 13th, 2006, 11:38 AM   #2
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 1,886
Rep Power: 5 Sane will become famous soon enough
Send a message via MSN to Sane
I'm guessing it's meant for debugging, to see how many times a function is being called. The only thing, is there's no argument to handle the function as a parameter. Once I added that in, and a default for "inc", I could make a demonstration.

def make_acc(func, start=0):
    """accumulator generator """
    curr = [start]
    def acc(inc=1):
        curr[0] += inc
        return curr[0]
    return acc

@make_acc # use make_acc for debugging purposes
def foo():
    return "bar"

print foo() #1
print foo() #2
print foo() #3
print foo() #4


# don't use "make_acc" 
def foo():
    return "bar"

print foo() #bar
print foo() #bar
print foo() #bar
print foo() #bar
So basically, you would append that decorator to any function, and instead of it being called, it will return how times it has been called.
Sane is offline   Reply With Quote
Old Aug 13th, 2006, 12:00 PM   #3
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 856
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
I understand how the accumulator function works, but how come the curr variable has to be a list? Why doesn't the following work?

def make_acc(start=0):
    """accumulator generator """
    curr = start
    def acc(inc):
        curr += inc
        return curr
    return acc
I get the error "UnboundLocalError: local variable 'curr' referenced before assignment".
titaniumdecoy is offline   Reply With Quote
Old Aug 14th, 2006, 2:33 PM   #4
Dietrich
Professional Programmer
 
Dietrich's Avatar
 
Join Date: Feb 2005
Posts: 434
Rep Power: 4 Dietrich is on a distinguished road
Wow Sane, I think you hit the hammer on the nail!

I think the list here behaves like a static variable.
__________________
I looked it up on the Intergnats!
Dietrich is offline   Reply With Quote
Old Aug 14th, 2006, 2:51 PM   #5
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 856
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Quote:
Originally Posted by Dietrich
I think the list here behaves like a static variable.
Yes, but why doesn't curr behave like a static variable when it is not a list?
titaniumdecoy is offline   Reply With Quote
Old Aug 14th, 2006, 3:11 PM   #6
Dietrich
Professional Programmer
 
Dietrich's Avatar
 
Join Date: Feb 2005
Posts: 434
Rep Power: 4 Dietrich is on a distinguished road
Quote:
Originally Posted by titaniumdecoy
Yes, but why doesn't curr behave like a static variable when it is not a list?
Because in your case the variable would be immutable, simply an integer.
To follow this up with an example:
# Python's version of a static variable
def static_num(list1=[0]):
    """The function's default is a list with one element = zero.
    Since the list is a mutable object it retains its address,
    as the function's default is created at compile time.
    Whatever you put into this list as element is retained too"""
    list1[0] += 1
    return list1[0]

print static_num()  # 1
print static_num()  # 2
print static_num()  # 3 
...
Well, not quite the same beast! Maybe Sane can help!
__________________
I looked it up on the Intergnats!

Last edited by Dietrich; Aug 14th, 2006 at 3:38 PM.
Dietrich is offline   Reply With Quote
Old Aug 15th, 2006, 5:45 AM   #7
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by titaniumdecoy
I understand how the accumulator function works, but how come the curr variable has to be a list? Why doesn't the following work?
In a nutshell, it's because Python's syntax does not distinguish between assignment and declaration. Instead, Python has to infer when a variable should be defined from the context; as a rule, it declares a new variable if no variable with the same name exists in the local scope.

Remember that "curr += inc" is equivalent to "curr = curr + inc", so it's an assignment. Because it's the first such assignment in the local scope, it's also a declaration. Thus, curr is first defined, and assigned the value "curr + inc". Unfortunately, because curr is defined before the assignment is evaluated, the curr in "curr + inc" refers to the variable you've just defined. Since you haven't assigned this curr a value yet, an error arises.

This problem can be circumvented by an explicit declaration keyword; let's call it "var". Then, the code would look like:
def make_acc(start=0):
    """accumulator generator """
    var curr = start
    def acc(inc):
        curr += inc
        return curr
    return acc
However, because Python does not have this keyword, instead relying on implicit declarations, we instead have to use the next best thing; a mutable variable. The most common mutable variable is a list
def make_acc(start=0):
    """accumulator generator """
    curr = [start]
    def acc(inc):
        curr[0] += inc
        return curr[0]
    return acc
This was pointed out to me by a fellow on Slashdot. He argued that Perl was more suited toward a more functional style of programming than Python (or even Ruby), because Perl supports explicit declarations (via my). I have to admit that he's right there. Subfunctions and scoping is one thing Perl does a bit better than its successors.
Arevos is offline   Reply With Quote
Old Aug 15th, 2006, 1:42 PM   #8
hydroxide
Programmer
 
Join Date: Apr 2005
Posts: 73
Rep Power: 4 hydroxide is on a distinguished road
To which I add:
def make_acc(start=0):
    def acc(inc):
        acc.curr += inc
        return acc.curr
    acc.curr = start
    return acc
... and now the circle is complete <evil grin>

As to where you'd use an accumulator generator - you could use it with a language where functional programming is more pleasant than OO, and you want to store state for (eg) an accounting program - ie you need to store many totals. You could use an accumulator generator for each. Even with an OO program using one probably decreases the chances of bugs - "=" rather than "+=", for instance. You could probably also use it usefully for something domain-specific-ish in (eg) Ruby since you don't need brackets to call it.

-T. *handwave* "These are not the droids you are looking for" *handwave*
hydroxide is offline   Reply With Quote
Old Aug 15th, 2006, 1:53 PM   #9
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Aha! A rather elegant solution to the problem you have there, hydroxide.
Arevos is offline   Reply With Quote
Old Aug 17th, 2006, 7:01 AM   #10
hydroxide
Programmer
 
Join Date: Apr 2005
Posts: 73
Rep Power: 4 hydroxide is on a distinguished road
Small bit of background that may help explain part of the comment: I originally posted that code on devshed as what I considered to be a prettier way of writing an acc gen (and by extension any stateful closure). I misread Dietrich's reply as where would _I_ use an acc gen (answer "Never") - sorry, D. Glad someone liked it .

Python is probably either getting an "outer" declaration or else the "global" declaration will look in successively outer scopes. Not sure if this will be 2.6 or 3.0 tho.

Cheers, -T.
hydroxide is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Compiling Maverik 6.2 (from C) megamind5005 C 16 May 3rd, 2006 5:41 PM
libraries matko C 1 Jan 22nd, 2006 2:12 PM
Php Postgresql Class Pizentios Show Off Your Open Source Projects 15 Jun 28th, 2005 9:55 AM
Jackpot game zorin Visual Basic 3 Jun 10th, 2005 1:19 PM
airport Log program using 3D linked List : problem reading from file gemini_shooter C++ 0 Mar 2nd, 2005 4:12 PM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 5:05 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC