Consider the following Python snippet regarding function composition:
from functools import reduce def compose(*funcs):
I have two questions:
- Can someone explain me the
compose operational logic? (How it works?) - Would it be possible (and how?) To get the same without using a shortcut for this?
I already looked here , here and here too , my problem does NOT understand what lambda or reduce means (I think I got, for example, that 2 in the usage example will be somewhat the first element in funcs to be composed). What I find harder to understand is the complexity of how the two lambda got merged / nested and mixed with *args, **kwargs here as the first reduce argument ...
EDIT:
First of all, @Martijn and @Borealid, thanks for your efforts and answers and for dedicating to me. (Sorry for the delay, I do this in my free time and don't always get much ...)
Ok, now come to the facts ...
About the 1st paragraph of my question:
First of all, I realized that I really did not get (but I hope I did it now) about these arguments *args, **kwargs variadic before that, at least **kwargs is optional (I good, good ?) This made me understand, for example, why mycompositefunc(2) works with this only one (without a keyword) argument passed.
Then I realized that the example would work even if replacing these *args, **args in the inner lambda with plain x . I assume that since in this example all 3 linked functions ( sin, cos, sqrt ) expect one (and only one) parameter ... and, of course, return one result ... so, more specifically, it works, because the first composite function expects only one parameter (the following, of course, will receive only one argument here, that is the result of the previous functions that are linked, so you CANNOT make functions that expect more than one argument after the first ... I know this a bit, but I I think you have what I'm trying to explain ...)
Now, having come to what remains a vague question for me:
lambda f, g: lambda *args, **kwargs: f(g(*args, **kwargs))
How does this lambda magic work?
With all the respect that you deserve, and I bear you, it seems to me that both of you are mistaken to come to the conclusion that the end result is sqrt(sin(cos(*args, **kw))) . Actually this cannot be, the order of operation of the sqrt function changes clearly: it is not the last, but the first.
I say this because:
>>> mycompositefunc(2) 0.1553124117201235
its result is equal
>>> sin(cos(sqrt(2))) 0.1553124117201235
then how do you get the error message
>>> sqrt(sin(cos(2))) [...] ValueError: math domain error
(which is due to an attempt to squareroot a negative float)
#PS for completeness: >>> sqrt(cos(sin(2))) 0.7837731062727799 >>> cos(sin(sqrt(2))) 0.5505562169613818
So, I understand that the composition of the functions will be made from the last to the first (that is, to compose (sin, cos, sqrt) => sin (cos (sqrt (x)))), but "why?" and how does this lambda magic work? still remains a little obscure to me ... Help / suggestions are greatly appreciated!
At the 2nd point (on transcribing essays without reduction)
@Martijn Pieters: your first lineup (“wrapped”) works and returns exactly the same result
>>> mp_compfunc = mp_compose(sin,cos,sqrt) >>> mp_compfunc(2) 0.1553124117201235
Instead of the deployed version, unfortunately, loops to RuntimeError: maximum recursion depth exceeded ...
@Borealid: your foo / bar example will not get more than two functions for composition, but I think it was just for explanations not intended to answer the second point, right?