[Tutor] Functional Programming in Python
WolfRage
wolfrage8765 at gmail.com
Thu Apr 2 21:26:53 CEST 2015
On 04/02/2015 01:07 PM, Alan Gauld wrote:
<SNIP>
> I'm not sure what you mean is impossible? The specific issues
> you are having or the general FP paradigm?
I mean achieving truely functional code, atleast to the extent of some
of the things that I have read. But in general I do not need nor want
any of those special features. I.E. single assignment, optimized tail
call, etc.
>
> Python has fairly good support for FP, much better than
> most non-FP-specific languages.
I agree.
<SNIP>
> Everything goes in functions which do not change their inputs and return
> outputs.
I am getting better at this.
>
> Use tools like itertools and functools to avoid explicit loops.
I am beginning to use them more.
>
>> What are your thoughts on Functional in Python?
>
> It's good enough to use where the problem suits FP. It's no
> more a pure FP language than it is a pure OOP language.
> But in both cases you can get close enough for practical
> purposes. What is your problem scenario that makes FP seem
> like the best idiom?
Since I am making a game, three things got out of control.
1. Managing transitions and instances of objects between transitions.
Like loading the Main Menu then starting a Game, then returning to the
Menu and Starting a New Game, the old game was still hanging around in
memory which becomes a problem on Phones.
2. Side effects have gotten out of hand, and so adding a feature often
meant adding bugs.
3. Duplication of code got out of hand. Several functions doing similar
things but slightly different. I turned this into pipe-lining to reduce
out the different cases and eliminate the duplication.
But since it is a game the amount of state does make FP seem very
difficult and thus the game is a mixture of OOP and FP, which I am glad
to see people saying mix as needed.
>
>> Currently I am re-writing functions to reduce their side effects.
>
> Good, nearly always the best way.
>
>> I am also removing the state from objects and putting it into a closure
>> type function.
>
> That may or may not be a good idea. FP object handling can
> get awfully messy and awfully inefficient.
>
>> However with callback based systems (GUI) this seemed impossible, so
>> instead I am abusing a coroutine to maintain the state of the
>> application.
>
> Trying to force a non-FP framework(eg a GUI)_ to work in an FP
> way is usually an exercise in frustration.
Yeah, it took me awhile to think about what to do in this case. Thus I
decided it was best to accept that the interface between the GUI and my
code had to be more OOP.
>
>> But is it abuse or does it seem like a good way to handle the callback
>> system? The benefit to me at this time is limited, but any errors in
>> state are confined to a single location, which is nice.
>
> That should be true in an OOP based system too. The whole point
> of OOP is to contain and hide state (as opposed to eliminating it)
I think since I am mostly self taught I perhaps failed to learn this
containment of state until recently. So before now it was fairly common
for my state to be spread out amongst several objects. It seems hard for
me to contain state in a OOP manor, just because it is so easy to use self.
>
>> What do you think about using a coroutine to handle state, how would you
>> do it better in a callback based system.
>
> Without seeing how you are doing it we can't comment on *better*.
> We need a baseline. Your approach may be brilliant, or it may
> be awful, we can't tell.
Yeah probably not brilliant. More like hopefully not completely stupid.
>
> But remember that there is no such thing as the perfect paradigm.
> FP has many strengths but it has many weaknesses too. As does OOP.
> Even procedural programming has advantages over OOP and FP in
> some circumstances. By all means learn the paradigms, but don't get hung
> up on any one. They all play a part.
Agreed. I am still trying to learn the right mixture.
The GUI is Kivy, but I could probably apply the same concept to QT.
Example of my Abused coroutine:
def coroutine(func):
# A decorator function that takes care of starting a coroutine
# automatically on call.
def start(*args, **kwargs):
cr = func(*args, **kwargs)
cr.send(None)
return cr
return start
@coroutine
def app_state(APP):
# APP = kivy.app.App.get_running_app() # So you know what APP is.
while True:
signal = yield
# Pass if signal is None or less than 1.
if signal >= 0 and signal < 1:
pass # Ignore this range
elif signal >= 1 and signal < 2:
if signal == 1.01: # Load Main Menu
print('Load File for Displaying Main Menu')
# This acts as a callback with the benefit of yielding
# to Kivy's main loop.
kivy.clock.Clock.schedule_once(APP.signal, 0)
yield 1.02
print('Add Main Menu to ScreenManager.')
kivy.clock.Clock.schedule_once(APP.signal, 0)
yield 1.03
print('Start Music for Main Menu')
# Other clean up that I do here.
# Remove Game from Screen Manager
# Delete References to Game
elif signal >= 2 and signal < 3:
if signal == 2.01:
print('Load File for Displaying Game')
kivy.clock.Clock.schedule_once(APP.signal, 0)
yield 2.02
print('Add Game to ScreenManager.')
kivy.clock.Clock.schedule_once(APP.signal, 0)
yield 2.03
print('Start Music for Main Menu')
# Other clean up that I do here.
# Remove Main Menu from Screen Manager
# Delete References to Main Menu
state = app_state(kivy.app.App.get_running_app())
kivy.app.App.get_running_app().signal = state.send
More information about the Tutor
mailing list