Home
Home Page
And again about functional programming on Python
Where the Python has come crawling?
Practical application OOP in PHP5
Functional programming in language Python
Approaches of language Python - an amusing example of optimization
Use ext/mysqli: Part I - the Review and the prepared expressions
How to receive the maximal result from registration in catalogues
XML-RPC In language Python
The API-specification of databases of language Python, version 2.0
Programming of the Web-client in language Python
Useful advice for job with XML
Future Web - behind semantics
Whether it is necessary to cancel spaces of names XML?
Use AJAX in ASP.NET
ASP .NET 2.0: Reference pages
Patterns of registration
What is ASP.NET. Installation and the test project.
Anatomy ASP.NET. ASP.NET in operation.
Server elements of management Continuation.
Links
 
topic


And again about functional programming on Python

Previous clauses{articles} have touched the basic concepts of functional programming (FP). This clause{article} will continue discussion, illustrating the additional opportunities mainly realized in library Xoltar Toolkit: partial function evaluation (Currying, karring), functions of the maximum{supreme} order (higher-order functions) and other concepts.



What is python?


Python - freely accessible, interpretive programming language of a high level developed by Guido van Rossumom (Guido van Rossum). He unites clear syntax with powerful (but it is unessential) object-oriented semantics. Python can be established on any platform and provides perfect compatibility at transition from one platform on another.



Linkage of expressions


Dissatisfied polureshenijami, one of readers - Richarda Davis (Richard Davies) - has lifted a question, whether we can move entirely linkages to separate expressions. Let's try understand, what for we can want it, and also we shall show wonderfully elegant way of it to achieve, given by the participant comp.lang.python.


Let's recollect class Bindings determined in the module functional all over again. Using properties of this class, we could guarantee, that the separate name has a unique value within the limits of area of the given block:



* -------Python FP session with guarded rebinding-------*

>>> from functional import *

>>> let = Bindings ()

>>> let.car = lambda lst: lst [0]

>>> let.car = lambda lst: lst [2]

Traceback (innermost last):

File " ", line 1, in?

File "d:toolsfunctional.py", line 976, in __ setattr __

raise BindingError, " Binding ' %s' cannot be modified. " % name

functional. BindingError: Binding 'car' cannot be modified.

>>> let.car (range (10))

0


With the help of class Bindings we managed to reach{achieve} desirable result within the limits of the module or function, but concerning separate expression we are powerless. Nevertheless, for family of ML-languages it is quite natural to create linkages within the limits of separate expression:



* --------Haskell expression-level name bindings--------*

- car (x:xs) = x - *could* create module-level binding

list_of_list = [[1,2,3], [4,5,6], [7,8,9]]

- 'where' clause for expression-level binding

firsts1 = [car x | x <-list_of_list] where car (x:xs) = x

- 'let' clause for expression-level binding

firsts2 = let car (x:xs) = x in [car x | x <-list_of_list]

- more idiomatic higher-order 'map' technique

firsts3 = map car list_of_list where car (x:xs) = x

- Result: firsts1 == firsts2 == firsts3 == [1,4,7]


Grehg EHving (Greg Ewing) has noticed, that we can reach{achieve} the same effect, having used list embeddings Python (list comprehensions); we even can make it almost so clear way, as in Haskell:



* ------Python 2.0 + expression-level name bindings------*

>>> list_of_list = [[1,2,3], [4,5,6], [7,8,9]]

>>> [car_x for x in list_of_list for car_x in (x [0],)]

[1, 4, 7]


This reception - accommodation of expression inside a single-element train in list embedding - does not allow to use linkage at a level of expressions with functions of the maximum{supreme} order. For use of such functions all of us still should use area of the block:



* -------Python block-level bindings with ' map () '-------*

>>> list_of_list = [[1,2,3], [4,5,6], [7,8,9]]

>>> let = Bindings ()

>>> let.car = lambda l: l [0]

>>> map (let.car, list_of_list)

[1, 4, 7]


It is quite good, though if we want to use map (), the area of linkage remains a little bit more widely, than we wanted that. Nevertheless, it is possible to persuade list embedding to do{make} for us linkage of names even if the list - not that it is necessary for us finally:



* ----" Stepping down " from Python list-comprehension----*

* Compare Haskell expression:

* result = func car_car

* where

* car (x:xs) = x

* car_car = car (car list_of_list)

* func x = x + x^2

>>> [func for x in list_of_list

... for car in (x [0],)

... for func in (car+car ** 2,)] [0]

2


In this example we have made arithmetic action above the first element of the first element of the list list_of_list and have simultaneously called this action (but only in the field of comprehensive expression). In quality of "optimization" it is possible to advise to create the list in length no more than one element as with the help of an index [0] at the end of expression we choose only the first element:



* ----Efficient stepping down from list-comprehension---*

>>> [func for x in list_of_list [:1]

... for car in (x [0],)

... for func in (car+car ** 2,)] [02


Functions of the maximum{supreme} order: partial function evaluation - karring [1] (currying)


Three most the general{common} functions of the maximum{supreme} order are built - in in Python: map (), reduce () and filter (). These functions use other functions in quality (some) parameters - that is why we name their functions of the maximum{supreme} order. Other functions of the maximum{supreme} order (but not these three) return objects - functions (function objects).


Python always gave programmers an opportunity to create own functions of the maximum{supreme} order due to the full status of functions as objects. Below the simple example by way of illustration is resulted:



* -----------Trivial Python function factory------------*

>>> def foo_factory ():

... def foo ():

... print " Foo function from factory "

... return foo

...

>>> f = foo_factory ()

>>> f ()

Foo function from factory


Program Xoltar Toolkit which I mentioned in previous clauses{articles}, contains a remarkable set of functions of the maximum{supreme} order. The majority of these functions given by the module functional, are available in set traditional functional programming languages, and their utility is checked up by long-term use. Perhaps, the most known and important function of the maximum{supreme} order traditionally is called curry (). She is named in honour logic KHaskella Karri (Haskell Curry), whose name names already mentioned programming language. In a basis karringa the assumption that (almost) any function can be considered{examined} as in part calculated function of one argument lays. That this idea worked, it is necessary that the value returned by function, itself could be function, but returned functions should be already or closer to end. This mechanism is similar to short circuit about which I told in previous clause{article} - each call karrirovanoj adds functions more than the data necessary for final calculation (the data are attached to procedure). We shall illustrate all over again karring with very simple example on Haskell, and then we shall repeat the same example on Python with the help of the module functional:



* -------------Currying a Haskell computation-----------*

computation a b c d = (a + b^2 + c^3 + d^4)

check = 1 + 2^2 + 3^3 + 5^4

fillOne = computation 1 - specify "a"

fillTwo = fillOne 2 - specify "b"

fillThree = fillTwo 3 - specify "c"

answer = fillThree 5 - specify "d"

- Result: check == answer == 657


And now on Python:



* -------------Currying a Python computation------------*

>>> from functional import curry

>>> computation = lambda a, b, c, d: (a + b ** 2 + c ** 3 + d ** 4)

>>> computation (1,2,3,5)

657

>>> fillZero = curry (computation)

>>> fillOne = fillZero (1) * specify "a"

>>> fillTwo = fillOne (2) * specify "b"

>>> fillThree = fillTwo (3) * specify "c"

>>> answer = fillThree (5) * specify "d"

>>> answer

657


Let's result one more example confirming, that between karringom and short circuit much in common. For this purpose, using curry (), we shall copy the simple program of calculation of the tax which code can be found in previous clause{article}:



* ------------Python curried tax calculations-----------*

from functional import *

taxcalc = lambda income, rate, deduct: (income-(deduct)) *rate

taxCurry = curry (taxcalc)

taxCurry = taxCurry (50000)

taxCurry = taxCurry (0.30)

taxCurry = taxCurry (10000)

print " Curried taxes due = ", taxCurry

print " Curried expression taxes due = ",

curry (taxcalc) (50000 (0.30) (10000)


As against short circuit, at use curry () it is necessary to fill in parameters in the certain order (from left to right). But notice, the class also is switched on in the module functional rcurry () for which readout begins with other end (from right to left).


Pay attention to the second the operator print in this example - on the one hand, it only - could be called trivial syntactic change simply taxcalc (50000,0.30,10000). But on the other hand, due to this there is understandable an idea that each function can be function of all one argument - rather unexpected idea for those who about these is unfamiliar.



Other functions of the maximum{supreme} order


Besides fundamental function curry (), in the module functional includes a number{line} of the most interesting functions of the maximum{supreme} order. Moreover, does not make the big work itself to write own functions of the maximum{supreme} order - with the help or without this module. Anyway, it is possible to use the ideas submitted in him.


Generally functions of the maximum{supreme} order behave as the "advanced" versions of standard functions map (), filter () and reduce (). In most cases they operate according to the following rule: " to accept function or functions and some lists as parameters, then to apply function (functions) to the list of parameters ". This rule gives tremendous opportunities for programming. Other principle " to accept a set of functions and to create the function combining them functionality ". And besides, numerous variations are possible{probable}. Let's look, that gives functional.


Functions sequential () and also () create the function based on sequence of other functions. Functions - components then can be called with identical argument (arguments). The main distinction between these two functions consists that in sequential () the list of functions is accepted as the first argument, and also () accepts the list of arguments (each of which should be function) variable length. In most cases them use for the sake of by-effects of making functions, however sequential () allows opcional`no to set, result of what function to return as the combined value:



* ----Sequential calls to functions (with same args)----*

>>> def a (x):

... print x,

... return "a"

...

>>> def b (x):

... print x*2,

... return "b"

...

>>> def c (x):

... print x*3,

... return "c"

...

>>> r = also (a, b, c)

>>> r


>>> r (5)

51015

'a'

>>> sequential ([a, b, c], main=c) ('x')

x xx xxx

'c'


Functions disjoin () and conjoin () are similar with sequential () and also () in the sense that they also create new functions which apply parameter (y) to several making functions. But disjoin () finds out, whether one of making functions "true" (true) returns even, and conjoin () finds out, whether return all functions "true". Thus when it is possible, logic of "short circuit" [2], therefore by their call the part of by-effects can not be shown. joinfuncs () it is similar on also (), but, as against it{her}, returns a train of results of making functions, instead of chooses one value.


While the above-stated functions cause many functions with identical parameters, functions any (), all () and none_of () allow to cause the same function for each value from the list. Generally they are similar to the built - in functions map (), filter () and reduce (). But, as against the last, these functions set bulevy (logic) questions concerning to a set of returned sizes. For example,



* ---------Ask about collections of return values-------*

>>> from functional import *

>>> isEven = lambda n: (n%2 == 0)

>>> any ([1,3,5,8], isEven)

1

>>> any ([1,3,5,7], isEven)

0

>>> none_of ([1,3,5,7], isEven)

1

>>> all ([2,4,6,8], isEven)

1

>>> all ([2,4,6,7], isEven)

0


Special interest for those who is not indifferent to mathematics, represents function of the maximum{supreme} order compose (). The composition forms a chain of several functions, directing return of one function on an input{entrance} following. The programmer combining of a little bit{some} functions, should watch{keep up} that that the output{exit} and an input{entrance} corresponded{met} to each other - but in fact it so in any case if the programmer uses returned value. The example explaining said is below resulted:



* -----------Creating compositional functions-----------*

>>> def minus7 (n): return n-7

...

>>> def times3 (n): return n*3

...

>>> minus7 (10)

3

>>> minustimes = compose (times3, minus7)

>>> minustimes (10)

9

>>> times3 (minus7 (10))

9

>>> timesminus = compose (minus7, times3)

>>> timesminus (10)

23

>>> minus7 (times3 (10))

23



Some recommendations


I hope, this review of functions of the maximum{supreme} order will stay interest to the certain style of thinking at the reader. Anyway, experiment with them. Try to create own functions of the maximum{supreme} order; some from them can appear rather useful and powerful. Share with me the achievements, and, probably, in future clause{article} we shall discuss original and remarkable ideas with which me readers continuously supply.